Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2849 connectés 

  FORUM HardWare.fr
  Programmation
  C++

  petit exemple: fabriquer votre propre opérateur ternaire

 


 Mot :   Pseudo :  
 
 Page :   1  2
Page Précédente
Auteur Sujet :

petit exemple: fabriquer votre propre opérateur ternaire

n°468034
Taz
bisounours-codeur
Posté le 25-07-2003 à 18:08:55  profilanswer
 

/!\ topic sérieux /!\
déconseillé aux débutants. Tout le monde peut lire ce topic et tester le code, mais j'aimerais que l'on reste focalisé sur la technique et pas sur le C++ lui même. Si il y a des points dans le code que vous ne comprenez pas, c'est sans doute une lacune. N'hésitez pas à créer des topics spécifiques (j'aimerais eviter des questions déplacées sur les constructeurs() : truc(chose), les operateur AutreType(), les déclarations imbriquées etc)
 
pour ceux que ça interesse... ce topic à pour but de présenter une technique avancée du C++. Je ne suis pas un véritable expert, donc je peux très bien raconter des bêtises et faire n'importe quoi.
 
Le C++ est langage où l'on manipule les objets par valeur et non par « référence » comme dans des langages comme Java ou Python.
 
Si on analyse l'expression
 
a = b * c
 
cela implique généralement et selon la sémantique habituelle, la création d'un objet temporaire:
 
tmp ( b * c )
a = tmp
 
dans beaucoup d'application ce genre de sémantique ainsi que la création de nombreux objets temporaires ne posent absolument aucun problème: le coup de la création/copie/destruction étant négligeable. Maintenant, vous avez une application où ces opérations ne sont pas du tout négligeables comme dans le cas de calcul scientifique.
 
Le but de ce topic est de montrer une technique permettant de réduire le nombre d'objets temporaires créés. Avant de commencer à vous l'expliquer, je signale qu'il existe une autre technique courremment utilisée qui est basée sur le concept de poignée (handle), c'est à dire que différents objets sont en mesures de partager des membres, et l'intégrité est assurée par un mécanisme de copie sur écriture (copy on write). Pour cela, on utilise souvent des pointeurs intelligents comme les boost::shared_ptr.
 
L'autre technique consiste à jongler sur les mécanismes de surcharge et de résolution de fonction. Je prends ici l'exemple des opérateurs arithmétique + et * mais celà fonctionne avec toutes les fonctions et tous les opérateurs, pour toutes les fonctions n-aires (mais celaest beaucoup plus long)
 
Simplement pour en revenir à l'expression
 
a = (b * c) + d  
 
on va essayer transmettre à a des références aux objets b, c et d et éviter ainsi la création de 2 objets temporaires. Pour réaliser ce mécanisme, on va se servir d'objets porteurs qui vous nous servir à transporter les références jusqu'à a.
cette expression va alors se décomposer
 
a = porteur*(b, c) + d
a = porteur*+(b, c, d)
 
et tou ça n'implique la création d'aucun objet temporaire. a dispose de références à b, c et d et peut librement effectuer les opérations qu'il souhaite et l'affectation.
 
 
bon apres, je sais pas trop expliquer, j'ai essayer de faire un petit exemple, sans doute critiquable. (Notez bien au passage l'implémentation des opérateurs binaires comme fonction externes utilisant les fonctions membres autour de l'affectation, c'est là une tres bonne méthode d'implémentation)
 

Code :
  1. //  source-highlight -v -doc -n -scpp -fhtml operator3.cpp
  2. #include <iostream>
  3. using namespace std;
  4. class Foo
  5. {
  6. public
  7.   struct MultScript;
  8.   struct AddScript;
  9.   struct AddMultScript;
  10.   Foo()
  11.   {
  12.     cout << "Foo()\n";
  13.   }
  14.   Foo(const Foo &other)
  15.   {
  16.     cout << "Foo(Foo)\n";
  17.   }
  18.   ~Foo()
  19.   {
  20.     cout << "~Foo()\n";
  21.   }
  22.   Foo & operator=(const Foo &other)
  23.   {
  24.     cout << "operator=(Foo)\n";
  25.     return *this;
  26.   }
  27.   Foo &operator=(const AddScript &as)
  28.   {
  29.     cout << "operator=(AddScrip)\n";
  30.     return *this;
  31.   }
  32.   Foo &operator=(const MultScript &as)
  33.   {
  34.     cout << "operator=(MultScrip)\n";
  35.     return *this;
  36.   }
  37.   Foo &operator=(const AddMultScript &as)
  38.   {
  39.     cout << "operator=(AddMultScrip)\n";
  40.     return *this;
  41.   }
  42.   Foo &operator+=(const Foo &other)
  43.   {
  44.     cout << "operator+=(Foo)\n";
  45.     return *this;
  46.   }
  47.   Foo &operator*=(const Foo &other)
  48.   {
  49.     cout << "operator*=(Foo)\n";
  50.     return *this;
  51.   }
  52. };
  53. struct Foo::AddScript
  54. {
  55.   AddScript(const Foo &lhs, const Foo &rhs)
  56.     : m_lhs(lhs),
  57.       m_rhs(rhs)
  58.   {}
  59.   operator Foo() const
  60.   {
  61.     cout << "AddScript::Foo()\n";
  62.     Foo tmp(m_lhs);
  63.     tmp+=m_rhs;
  64.     return tmp;
  65.   }
  66.   const Foo &m_lhs;
  67.   const Foo &m_rhs;
  68. };
  69. struct Foo::MultScript
  70. {
  71.   MultScript(const Foo &lhs, const Foo &rhs)
  72.     : m_lhs(lhs),
  73.       m_rhs(rhs)
  74.   {}
  75.   operator Foo() const
  76.   {
  77.     cout << "MultScript::Foo()\n";
  78.     Foo tmp(m_lhs);
  79.     tmp*=m_rhs;
  80.     return tmp;
  81.   }
  82.   const Foo &m_lhs;
  83.   const Foo &m_rhs;
  84. };
  85. struct Foo::AddMultScript
  86. {
  87.   AddMultScript(const Foo &a, const Foo &b, const Foo &c)
  88.     : m_a(a),
  89.       m_b(b),
  90.       m_c(c)
  91.   {}
  92.   operator Foo() const
  93.   {
  94.     cout << "AddMultScript::Foo()\n";
  95.     Foo prod(m_b);
  96.     prod*=m_c;
  97.     Foo sum(m_a);
  98.     sum+=prod;
  99.    
  100.     return sum;
  101.   }
  102.   const Foo &m_a;
  103.   const Foo &m_b;
  104.   const Foo &m_c;
  105. };
  106. Foo::MultScript operator*(const Foo &rhs, const Foo &lhs)
  107. {
  108.   cout << "operator*(Foo, Foo)\n";
  109.   return Foo::MultScript(rhs, lhs);
  110. }
  111. Foo::AddScript operator+(const Foo &rhs, const Foo &lhs)
  112. {
  113.   cout << "operator+(Foo, Foo)\n";
  114.   return Foo::AddScript(rhs, lhs);
  115. }
  116. Foo::AddMultScript operator+(const Foo &a, const Foo::MultScript &ms)
  117. {
  118.   cout << "operator+*(Foo, Foo::MultScrip)\n";
  119.   return Foo::AddMultScript(a, ms.m_lhs, ms.m_rhs);
  120. }
  121. int main()
  122. {
  123.   Foo a, b, c, d;
  124.   cout << "\n\n";
  125.   cout << "a=b+c\n";
  126.   a=b+c;
  127.   cout << '\n';
  128.   cout << "a=c*d\n";
  129.   a=c*d;
  130.   cout << '\n';
  131.   cout << "a=b+c+d\n";
  132.   a=b+c+d;
  133.   cout << '\n';
  134.   cout << "a=b*c*d\n";
  135.   a=b*c*d;
  136.   cout << '\n';
  137.   cout << "a=a+b+c+d\n";
  138.   a=a+b+c+d;
  139.   cout << '\n';
  140.   cout << "a=a*b*c*d\n";
  141.   a=a*b*c*d;
  142.   cout << '\n';
  143.   cout << "a=b+c*d\n";
  144.   a=b+c*d;
  145.   cout << '\n';
  146. }


 
Enjoy  :hello:

mood
Publicité
Posté le 25-07-2003 à 18:08:55  profilanswer
 

n°468052
LetoII
Le dormeur doit se réveiller
Posté le 25-07-2003 à 18:25:50  profilanswer
 

Mouai, concepte intéressant...


---------------
Le Tyran
n°468122
Joel F
Real men use unique_ptr
Posté le 25-07-2003 à 20:00:35  profilanswer
 

Tres interressant, j'utilise une technique similaire pour générer duc ode utilisant des opérations ternaires en AltiVec à partir de l'écriture a*b+c.  Tres tres bon exposé :D

n°468144
skeye
Posté le 25-07-2003 à 20:42:29  profilanswer
 

Je flagge...pas le temps de lire de suite et certainement au-dessus de mon niveau, mais j'aime apprendre!:jap:

n°468150
polo021
Posté le 25-07-2003 à 20:56:50  profilanswer
 

pas facile a comprendre tout ca!
Est ce que tu pourrais expliquer ceci:

Code :
  1. Foo::AddScript operator+(const Foo &rhs, const Foo &lhs)
  2.   {
  3.       cout << "operator+(Foo, Foo)\n";
  4.       return Foo::AddScript(rhs, lhs);//que fait cette ligne exactement?
  5.   }


 
 
La sortie pour ceux qui ne peuvent pas executer :

Foo()
Foo()
Foo()
Foo()
 
 
a=b+c
operator+(Foo, Foo)
operator=(AddScrip)
 
a=c*d
operator*(Foo, Foo)
operator=(MultScrip)
 
a=b+c+d
operator+(Foo, Foo)
AddScript::Foo()
Foo(Foo)
operator+=(Foo)
Foo(Foo)
~Foo()
operator+(Foo, Foo)
operator=(AddScrip)
~Foo()
 
a=b*c*d
operator*(Foo, Foo)
MultScript::Foo()
Foo(Foo)
operator*=(Foo)
Foo(Foo)
~Foo()
operator*(Foo, Foo)
operator=(MultScrip)
~Foo()
 
a=a+b+c+d
operator+(Foo, Foo)
AddScript::Foo()
Foo(Foo)
operator+=(Foo)
Foo(Foo)
~Foo()
operator+(Foo, Foo)
AddScript::Foo()
Foo(Foo)
operator+=(Foo)
Foo(Foo)
~Foo()
operator+(Foo, Foo)
operator=(AddScrip)
~Foo()
~Foo()
 
a=a*b*c*d
operator*(Foo, Foo)
MultScript::Foo()
Foo(Foo)
operator*=(Foo)
Foo(Foo)
~Foo()
operator*(Foo, Foo)
MultScript::Foo()
Foo(Foo)
operator*=(Foo)
Foo(Foo)
~Foo()
operator*(Foo, Foo)
operator=(MultScrip)
~Foo()
~Foo()
 
a=b+c*d
operator*(Foo, Foo)
operator+*(Foo, Foo::MultScrip)
operator=(AddMultScrip)
 
~Foo()
~Foo()
~Foo()
~Foo()
Press any key to continue

n°468156
Taz
bisounours-codeur
Posté le 25-07-2003 à 21:06:22  profilanswer
 

:heink: j'avais dit pas de question à la con.... je vois pas ce que tu comprends pas: a) il y a pas de constructeur par defaut pour les classes *Script b) on construit l'objet qu'on retourne (normal quoi)
 
 
edit : « Press any key to continue »
ho le windozien


Message édité par Taz le 25-07-2003 à 21:08:51
n°468157
polo021
Posté le 25-07-2003 à 21:08:36  profilanswer
 

++Taz a écrit :

:heink:
 
 
edit : « Press any key to continue »
ho le windozien  


ben ouais c'est pas sencé appeler Foo::AddScript(rhs, lhs)???
Or on y est dans addscript  :heink:  
 
Mais bon je connais plus le C que le c++
 
 
edit : j'ai deja assez de mal comme ca :o


Message édité par polo021 le 25-07-2003 à 21:09:52
n°468160
Taz
bisounours-codeur
Posté le 25-07-2003 à 21:09:41  profilanswer
 

polo021 a écrit :


ben ouais c'est pas sencé appeler Foo::AddScript(rhs, lhs)???
Or on y est dans addscript  :heink:  
 
Mais bon je connais plus le C que le c++

:pfff: merci de ta participation, au revoir

n°468161
polo021
Posté le 25-07-2003 à 21:10:32  profilanswer
 

++Taz a écrit :

:pfff: merci de ta participation, au revoir


 :bounce: explique

n°468164
Taz
bisounours-codeur
Posté le 25-07-2003 à 21:12:46  profilanswer
 

polo021 a écrit :


 :bounce: explique

:heink: que je sache, en C comme en C++, le prototype d'une fonction, c'est
 
<type de retour> nomDeLaFonction([<argument>])
 
je crois que tu ne sais pas ça. franchement je m'attendais pas à ça comme question, on est vendredi mais quand meme

mood
Publicité
Posté le 25-07-2003 à 21:12:46  profilanswer
 

n°468170
polo021
Posté le 25-07-2003 à 21:22:58  profilanswer
 

disons plutot : a quoi sert ceci alors

Code :
  1. struct Foo::AddScript
  2.   {
  3.       AddScript(const Foo &lhs, const Foo &rhs)
  4.         : m_lhs(lhs),
  5.           m_rhs(rhs)
  6.       {}
  7.    
  8.       operator Foo() const
  9.       {
  10.           cout << "AddScript::Foo()\n";
  11.      
  12.           Foo tmp(m_lhs);
  13.           tmp+=m_rhs;
  14.           return tmp;
  15.       }
  16.    
  17.       const Foo &m_lhs;
  18.       const Foo &m_rhs;
  19.   };

c bien ca que tu appeles quand tu fais Foo::AddScript(rhs, lhs), n'est cce pas

n°468171
Taz
bisounours-codeur
Posté le 25-07-2003 à 21:26:56  profilanswer
 

deux 2 choses l'une:
- tu n'a pas lu l'explication sur le role des classes Script
- « déconseillé aux débutants », pour moi c'est la première fois que tu vois une classe: on ne peut pas faire plus simple que les classes Script. si tu veux apprendre le C++, regarde les bibliolinks, si tu veux qu'on t'aide à créer ta première classe, on t'aidera, si tu veux un conseille de livre, je te donnerai des références. Mais là je peux rien pour toi. En tout cas pas dans ce topic.


Message édité par Taz le 25-07-2003 à 21:27:34
n°468172
polo021
Posté le 25-07-2003 à 21:38:52  profilanswer
 

restons en là alors [:spamafote]

n°468174
Taz
bisounours-codeur
Posté le 25-07-2003 à 21:42:49  profilanswer
 

polo021 a écrit :

restons en là alors [:spamafote]

ben fais un autre topic / envoie moi un PM avec le code de AddScript et que te le commente ligne par ligne

n°468202
bjone
Insert booze to continue
Posté le 25-07-2003 à 23:18:17  profilanswer
 

interressant je me suis dérouler le bordel dans la tête :D (ça fait mal mais ça passe)
=> technique notée dans un coin :D

n°468205
Taz
bisounours-codeur
Posté le 25-07-2003 à 23:34:12  profilanswer
 

tiens moi j'ai pas la même trace que polo
 

Foo()
Foo()
Foo()
Foo()
 
 
a=b+c
operator+(Foo, Foo)
operator=(AddScrip)
 
a=c*d
operator*(Foo, Foo)
operator=(MultScrip)
 
a=b+c+d
operator+(Foo, Foo)
AddScript::Foo()
Foo(Foo)
operator+=(Foo)
operator+(Foo, Foo)
operator=(AddScrip)
~Foo()
 
a=b*c*d
operator*(Foo, Foo)
MultScript::Foo()
Foo(Foo)
operator*=(Foo)
operator*(Foo, Foo)
operator=(MultScrip)
~Foo()
 
a=a+b+c+d
operator+(Foo, Foo)
AddScript::Foo()
Foo(Foo)
operator+=(Foo)
operator+(Foo, Foo)
AddScript::Foo()
Foo(Foo)
operator+=(Foo)
operator+(Foo, Foo)
operator=(AddScrip)
~Foo()
~Foo()
 
a=a*b*c*d
operator*(Foo, Foo)
MultScript::Foo()
Foo(Foo)
operator*=(Foo)
operator*(Foo, Foo)
MultScript::Foo()
Foo(Foo)
operator*=(Foo)
operator*(Foo, Foo)
operator=(MultScrip)
~Foo()
~Foo()
 
a=b+c*d
operator*(Foo, Foo)
operator+*(Foo, Foo::MultScrip)
operator=(AddMultScrip)
 
~Foo()
~Foo()
~Foo()
~Foo()


 
polo à des
 
Foo(Foo)
~Foo()  
 
je crée un nouvo topic pour en parler et j'essaye de me renseigner

n°468321
leneuf22
Posté le 26-07-2003 à 10:37:47  profilanswer
 

polo021 a écrit :


ben ouais c'est pas sencé appeler Foo::AddScript(rhs, lhs)???
Or on y est dans addscript  :heink:  
 
Mais bon je connais plus le C que le c++
 
 
edit : j'ai deja assez de mal comme ca :o


 
AddScript est une classe : on est dans opérator+, qui appelle le constructeur de la classe.
-> AddScript n'est pas une fonction : achète des lunettes :)

n°468324
Taz
bisounours-codeur
Posté le 26-07-2003 à 10:41:54  profilanswer
 

leneuf22 a écrit :


 
AddScript est une classe : on est dans opérator+, qui appelle le constructeur de la classe.
-> AddScript n'est pas une fonction : achète des lunettes :)

il a fait un topic exprès
http://forum.hardware.fr/forum2.ph [...] h=&subcat=

n°468328
polo021
Posté le 26-07-2003 à 10:45:11  profilanswer
 

leneuf22 a écrit :


 
AddScript est une classe : on est dans opérator+, qui appelle le constructeur de la classe.
-> AddScript n'est pas une fonction : achète des lunettes :)

:sol:  
Comprends mieux maintenant [:ddr555]

n°468601
Taz
bisounours-codeur
Posté le 26-07-2003 à 21:11:58  profilanswer
 

si ce genre de petite mémo plait, j'en referais peut être. Non?

n°468731
schnapsman​n
Zaford Beeblefect
Posté le 27-07-2003 à 01:39:05  profilanswer
 

Taz a écrit :

si ce genre de petite mémo plait, j'en referais peut être. Non?


 
[:calin]
 
http://membres.lycos.fr/cybear/Forum/topicR.gif
 
 
C'est bieng ce genre de wrappers, mais il faut bien en mesurer la portée.
Par exemple avec ce genre d'opérations:
 

Code :
  1. Foo a,b,c,d,e,r;
  2. r=a+b+c+e;


 
On n'économise qu'un objet temporaire Foo avec le wraper AddScript au lieu de la méthode classique (i.e friend Foo Foo::operator+(const Foo&, const Foo& )).


Message édité par schnapsmann le 27-07-2003 à 01:46:37

---------------
From now on, you will speak only when spoken to, and the first and last words out of your filthy sewers will be "Sir!"
n°468742
Taz
bisounours-codeur
Posté le 27-07-2003 à 01:48:59  profilanswer
 

ben c'est déjà pas mal, et puis si tu te réfères au titre du topic, ce n'est pas l'objet du topic. mais je considere que c'est déjà un petit plus non négligeable. pas possible de faire du quaternaire avec que des + avec la meme technique par ce que c'est la meme précédence, c'est donc évalué comme a+b+c+d = ((a+b)+c)+d)


Message édité par Taz le 27-07-2003 à 01:59:55
n°468749
schnapsman​n
Zaford Beeblefect
Posté le 27-07-2003 à 01:58:17  profilanswer
 

Taz a écrit :

ben c'est déjà pas mal, et puis si tu te réfères au titre du topic, ce n'est pas l'objet du topic. mais je considere que c'est déjà un petit plus non négligeable. et puis la voix est ouverte pour faire un opérateur quaternaire (y a plus qu'a rajouté une classe AddAddscript tres simple et a surchargé + et c'est réglé)


 
Mais oui je n'ai pas prétendu le contraire  [:calin]  
 
Dommage qu'on ne puisse pas bidouiller les précédences et associativités des opérateurs selon leur type (comme en ocaml) ce qui permettrait des optimisations automatiques pour tous les opérateurs n-aires.


---------------
From now on, you will speak only when spoken to, and the first and last words out of your filthy sewers will be "Sir!"
n°468756
Taz
bisounours-codeur
Posté le 27-07-2003 à 02:09:55  profilanswer
 

j'ai edité, mais je complète: la seule bidouille qu'on peut ajouter permet de réduire la durée de vie des objets temporaires, on peut alors obtenir au lieu de ça  
 

a=a+b+c+d
operator+(Foo, Foo)
Add2Script::Foo()
Foo(Foo)
operator+=(Foo)
operator+(Foo, Foo)
Add2Script::Foo()
Foo(Foo)
operator+=(Foo)
operator+(Foo, Foo)
operator=(Add2Scrip)
~Foo()
~Foo()


 
ceci
 
 

a=a+b+c+d
operator+(Foo, Foo)
operator+(Foo::Add2Script, Foo)
Add2Script::Foo()
Foo(Foo)
operator+=(Foo)
~Foo()
operator+(Foo::Add2Script, Foo)
Add2Script::Foo()
Foo(Foo)
operator+=(Foo)
~Foo()
operator=(Add2Script)

 
 
c'est peut etre pas mal de changer la précédence/priorité, mais je sais pas si c'est vraiment source de confusion à ce moment là... et au niveaux des conversion, y a pas de problème?

n°468758
Taz
bisounours-codeur
Posté le 27-07-2003 à 02:10:56  profilanswer
 

cela dit ça doit etre difficile de définir une relation pyramidale pour la resolution d'une expression, ça va contre le principe d'évaluation de gauche à droite..., donc je saisis pas trop comment le changement de priorité change quelque chose: tu ne peux pas dire: l'addition de ces 2 types est prioritaire à l'addition de ces 2 types... si? et ça marche comment si ton opérateur n'est pas symétrique? je peux comprendre l'interet mais je suis pas sur que ça soit une bonne chose. et le C++ est ce qu'il est. on surcharge, on ne définit pas, donc ce n'est pas possible de changer la priorité. enfin, là n'est pas la question, on est pas vraiment là pour faire des comparaisons...


Message édité par Taz le 27-07-2003 à 02:26:10
n°468765
schnapsman​n
Zaford Beeblefect
Posté le 27-07-2003 à 02:23:02  profilanswer
 

Taz a écrit :

cela dit ça doit etre difficile de définir une relation pyramidale pour la resolution d'une expression, ça va contre le principe d'évaluation de gauche à droite..., donc je saisis pas trop comment le changement de priorité change quelque chose: tu ne peux pas dire: l'addition de ces 2 types est prioritaire à l'addition de ces 2 types... si?


 
au temps pour moi, il s'agit plutot de privilégier l'opérateur de plus grande arité sur les autres. C'est faisable avec un parser LALR1.


---------------
From now on, you will speak only when spoken to, and the first and last words out of your filthy sewers will be "Sir!"
n°468767
Taz
bisounours-codeur
Posté le 27-07-2003 à 02:27:01  profilanswer
 

SchnapsMann a écrit :


 
au temps pour moi, il s'agit plutot de privilégier l'opérateur de plus grande arité sur les autres. C'est faisable avec un parser LALR1.

:heink: en infixé, c'est faisable? tu fais une rapide explication/exemple ? j'ai du mal avec les opérateurs b-aires n>2 en infixé. je réfléchis, et c'est possible qu'en pas infixé il me semble


Message édité par Taz le 27-07-2003 à 02:33:30
n°468784
schnapsman​n
Zaford Beeblefect
Posté le 27-07-2003 à 02:56:17  profilanswer
 

Taz a écrit :

:heink: en infixé, c'est faisable? tu fais une rapide explication/exemple ? j'ai du mal avec les opérateurs b-aires n>2 en infixé


 
rapide non  :o  
 
Il faut se placer dans le cadre d'un compilo LR1 en fé :o
Ce qui permet de changer les règles de décalage/réduction suivant le type de token en haut de la pile. NB: c'est tjrs de l'infixe mais c'est faisable... c'est justement une limitation des compilos LALR1 qui se contentent de "simples" tables de shift/reduce pour effectuer le parsing.
 
Ensuite l'idée c'est de raffiner la règle de réécriture d'un opérateur pour le type dont tu veux optimiser l'opérateur n-aire, en changeant son associativité à droite (comme pour le '=' classiquement).


Message édité par schnapsmann le 27-07-2003 à 02:58:14

---------------
From now on, you will speak only when spoken to, and the first and last words out of your filthy sewers will be "Sir!"
n°468785
Taz
bisounours-codeur
Posté le 27-07-2003 à 02:59:50  profilanswer
 

ok, j'avais po vu ça comme ça

n°469701
Joel F
Real men use unique_ptr
Posté le 28-07-2003 à 13:37:26  profilanswer
 

Retour au topic.
Taz il me semble que ton exemple ne marche pas si bien que ca ...
 
En effet, les operateurs Foo() appellent une à deux fois le constructeur de Foo ... (pour sum et prod non ?)  
DONC : il a bien construction d'objet temporaire ??
Ou alors les opérateurs de transtypage entre classes ont un comportement spécial qui m'est inconnu ?? (et donc éclaircissement stp)
 
De plus, si on veut ajouter une donnée dans Foo (style un double) il faut modifier lourdement le code :
 

Code :
  1. class Foo {
  2.   public:
  3.   struct AddScript
  4.   {
  5.       AddScript(const Foo & lhs, const Foo & rhs)
  6.   :m_lhs(lhs), m_rhs(rhs) {}
  7.    
  8.       const Foo & m_lhs;
  9.       const Foo & m_rhs;
  10.   };
  11.   struct MultScript
  12.   {
  13.       MultScript(const Foo & lhs, const Foo & rhs)
  14. :m_lhs(lhs), m_rhs(rhs) {}
  15.  
  16.       const Foo & m_lhs;
  17.       const Foo & m_rhs;
  18.   };
  19.   struct AddMultScript
  20.   {
  21.       AddMultScript(const Foo& a, const Foo& b, const Foo& c)
  22. :m_a(a), m_b(b), m_c(c) {}
  23.       const Foo & m_a;
  24.       const Foo & m_b;
  25.       const Foo & m_c;
  26.    };
  27.     Foo(double in):d(in) {
  28. cout << "Foo()\n";
  29.     }
  30.    
  31.     Foo(const Foo & other):d(other.d) {
  32. cout << "Foo(Foo)\n";
  33.     }
  34.    
  35.     ~Foo() {
  36. cout << "~Foo()\n";
  37.     }
  38.     Foo & operator=(const Foo & other) {
  39. cout << "operator=(Foo)\n";
  40. d = other.d;
  41. return *this;
  42.     }
  43.     Foo & operator=(const AddScript & as) {
  44. cout << "operator=(AddScrip)\n";
  45. d = as.m_lhs.d+as.m_rhs.d;
  46. return *this;
  47.     }
  48.     Foo & operator=(const MultScript & as) {
  49. cout << "operator=(MultScrip)\n";
  50. d = as.m_lhs.d*as.m_rhs.d;
  51. return *this;
  52.     }
  53.     Foo & operator=(const AddMultScript & as) {
  54. cout << "operator=(AddMultScrip)\n";
  55. d = as.m_a.d*as.m_b.d+as.m_c.d;
  56. return *this;
  57.     }
  58.     Foo & operator+=(const Foo & other) {
  59. cout << "operator+=(Foo)\n";
  60. d+=other.d;
  61. return *this;
  62.     }   
  63.     Foo & operator*=(const Foo & other) {
  64. cout << "operator*=(Foo)\n";
  65. d*=other.d;
  66. return *this;
  67.     }
  68.     double d;
  69. };
  70. Foo::MultScript operator*(const Foo & rhs, const Foo & lhs)
  71. {
  72.     cout << "operator*(Foo, Foo)\n";
  73.     return Foo::MultScript(rhs, lhs);
  74. }
  75. Foo::AddScript operator+(const Foo & rhs, const Foo & lhs)
  76. {
  77.     cout << "operator+(Foo, Foo)\n";
  78.     return Foo::AddScript(rhs, lhs);
  79. }
  80. Foo::AddMultScript operator+(const Foo & a, const Foo::MultScript & ms)
  81. {
  82.     cout << "operator+*(Foo, Foo::MultScrip)\n";
  83.     return Foo::AddMultScript(a, ms.m_lhs, ms.m_rhs);
  84. }
  85. int main()
  86. {
  87.     Foo a(1), b(2), c(3), d(4);
  88.     cout << "\n\n";
  89.     cout << "a=b+c\n";
  90.     a = b + c;
  91.     cout << "a=" << a.d << endl;
  92.     cout << '\n';
  93.     cout << "a=c*d\n";
  94.     a = c * d;
  95.     cout << '\n';
  96.     cout << "a=b+c*d\n";
  97.     a = b + c * d;
  98.     cout << '\n';
  99. }

 
 
La ca marche, la valeur de d est modifié corretement ET aucun objet temporaire n'est crée. Evidemment, il est nécessaire de surcharger + et * pour qu'ils gérent les cas :
 
Foo + xxScript
xxScript + Foo
xxScript + xxScript
 
Foo * xxScript
xxScript * Foo
xxScript * xxScript
 
Voila ... qu'en penses-tu ??

n°469706
LetoII
Le dormeur doit se réveiller
Posté le 28-07-2003 à 13:41:12  profilanswer
 

Joel F a écrit :

Retour au topic.
Taz il me semble que ton exemple ne marche pas si bien que ca ...
 
En effet, les operateurs Foo() appellent une à deux fois le constructeur de Foo ... (pour sum et prod non ?)  
DONC : il a bien construction d'objet temporaire ??
Ou alors les opérateurs de transtypage entre classes ont un comportement spécial qui m'est inconnu ?? (et donc éclaircissement stp)
 
 


 
 :jap:  
Sauf optimisation du compilo y a bien ndouble appel du constructeur de recopie.


Message édité par LetoII le 28-07-2003 à 13:41:32

---------------
Le Tyran
n°469717
Taz
bisounours-codeur
Posté le 28-07-2003 à 13:49:52  profilanswer
 

je vois pas trop de quel cas tu parle? pour a+b, a*b et a*b+c, je ne vois d'objet temporaire?

n°469721
LetoII
Le dormeur doit se réveiller
Posté le 28-07-2003 à 13:51:44  profilanswer
 

Taz a écrit :

je vois pas trop de quel cas tu parle? pour a+b, a*b et a*b+c, je ne vois d'objet temporaire?


 
C dans les operateurs de transtypage vers foo, même s'ils servent pas pour les calculs, y a un petit pb dedans.


---------------
Le Tyran
n°469729
Taz
bisounours-codeur
Posté le 28-07-2003 à 13:55:19  profilanswer
 

Moi je ne vois pas de problème. c'est réalisé de manière la plus atomique possible. je vois meme pas la difference avec ton code, si ce n'est qu'il se passe vraiment quelque chose dedans

n°469742
umag
deux yeux sinon rien
Posté le 28-07-2003 à 14:01:25  profilanswer
 

Rien que là, il y a un truc qui me gêne un peu :
 

Code :
  1. struct Foo::AddMultScript
  2. {
  3. AddMultScript(const Foo &a, const Foo &b, const Foo &c)
  4.    : m_a(a),
  5.      m_b(b),
  6.      m_c(c)
  7. {}
  8. operator Foo() const
  9. {
  10.    cout << "AddMultScript::Foo()\n";
  11.    // et de un objet temporaire
  12.    Foo prod(m_b);
  13.    prod*=m_c;
  14.    // et de deux
  15.    Foo sum(m_a);
  16.    sum+=prod; 
  17.      
  18.     return sum;
  19. }
  20. const Foo &m_a;
  21. const Foo &m_b;
  22. const Foo &m_c;
  23. };

 
 
La création des objets temporaires n'apparaît pas dans les logs parce que j'ai l'impression qu'à aucun moment tu ne fais réellement l'opération arithmétique (pas d'appel au transtypage par l'opérateur Foo(), comme disait Leto2).
Ou alors j'ai rien compris, évidemment...

n°469745
LetoII
Le dormeur doit se réveiller
Posté le 28-07-2003 à 14:03:25  profilanswer
 

Taz a écrit :

Moi je ne vois pas de problème. c'est réalisé de manière la plus atomique possible. je vois meme pas la difference avec ton code, si ce n'est qu'il se passe vraiment quelque chose dedans


 
La différence c qu'il a virré les operateurs de transtypage... J'ai pas regardé en détail mais oui apparement c la même chose que ce que tu as fait  [:ddr555]


Message édité par LetoII le 28-07-2003 à 14:03:46

---------------
Le Tyran
n°469752
LetoII
Le dormeur doit se réveiller
Posté le 28-07-2003 à 14:05:55  profilanswer
 

umag a écrit :

Rien que là, il y a La création des objets temporaires n'apparaît pas dans les logs parce que j'ai l'impression qu'à aucun moment tu ne fais réellement l'opération arithmétique (pas d'appel au transtypage par l'opérateur Foo(), comme disait Leto2).
Ou alors j'ai rien compris, évidemment...


 
Ben c fait exprès qu'on passe pas par le transtypage, justement pour pas créer d'objet intermédiaire.


---------------
Le Tyran
n°469757
Taz
bisounours-codeur
Posté le 28-07-2003 à 14:09:07  profilanswer
 

en fait y a besoin des opérateurs de transtypage, à moins fournir des constructeurs, sinon voif F(Foo) ne peut fonctionner avec F(a+b)
 
après ça m'a parru plus élégant et passe partout. c'est vrai que pour a+b+c, on peut encore spécialiser avec une classe Add3Script. mais le pincipal avantage que je vois, c'est qu'avec les opérateurs de conversion, on peut tres bien envisager ce genre de technique avec n'importe quelle classe sans avoir besoin de la modifier.

n°469770
umag
deux yeux sinon rien
Posté le 28-07-2003 à 14:13:40  profilanswer
 

LetoII a écrit :


 
Ben c fait exprès qu'on passe pas par le transtypage, justement pour pas créer d'objet intermédiaire.


 
Ben oui, c'est le principe... ;)
 
Mais il faut quand même faire l'opération quelque part, non ?
 
Donc l'opération, on la fait par exemple là pour le *+ avec un double :

Code :
  1. Foo & operator=(const AddMultScript & as)
  2. {
  3.    cout << "operator=(AddMultScrip)\n";
  4.    d = as.m_a.d*as.m_b.d+as.m_c.d; 
  5.    return *this;
  6. }

 
Et dans ce cas il n'y a effectivement pas d'objet temporaire créé...
Mais il fallait le dire, c'est tout.

n°469771
Taz
bisounours-codeur
Posté le 28-07-2003 à 14:14:44  profilanswer
 

c'était un peu le but du topic non  :pt1cable:

mood
Publicité
Posté le   profilanswer
 

 Page :   1  2
Page Précédente

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C++

  petit exemple: fabriquer votre propre opérateur ternaire

 

Sujets relatifs
Cherche exemple de menu dhtml verticalepb d'operateur
petit problème de largeur pour une balise divDévelopper sa propre messagerie mail : c'est dur?
Surcharge d operateur = et virtual , ca va ensemble ?[C / GNU] petit doute sur strncpy
Petit probleme de client smtp[FLASH] J'ai un petit problème de séquence ?
[VC++] Compiler un petit bout de C du site Microsoft !petit problème avec une classe PHP
Plus de sujets relatifs à : petit exemple: fabriquer votre propre opérateur ternaire


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR