Surcharge de l'Opérateur Virgule

Surcharge de l'Opérateur Virgule - C++ - Programmation

Marsh Posté le 27-04-2004 à 20:30:56    

Introduction :
Ce topic reprend un peu l'esprit des quelques topics postés cet été
sur la programmation template et autre technique de sioux. Même si l'interet
pour ces posts semblent avoir faibli, j'ai décidé d'un commun accord avec moi
même d'en rajouter quelques uns :)
 
Ce topic a pour vocation de montrer l'utilisation saugrenue de la surcharge de l'opérateur virgule.
 
Mise en Oeuvre :
Tout d'abord :heink:
Oui, j'ai bien parler de l'operateur virgule (operator,() pour les intimes).
Celui la même que bon nombre d'entre vous n'ont jamais, Ô grand jamais, penser à surcharger.
Et bien, tant pis, on va le faire quand même.
 
L'interet ??? Considerons une classe ressemblant à std::vector<double> :
 

Code :
  1. class TableauDouble
  2. {
  3.   public :
  4.  
  5.   TableauDouble(size_t size, double val=0);
  6.   virtual ~TableauDouble();
  7.  
  8.   // etc ...
  9.  
  10.   // Les méthodes importantes :
  11.  
  12.   double operator[](size_t i) const { return data[i]; }
  13.   double& operator[](size_t i) { return data[i]; }
  14.   double* begin() { return data; }
  15.   double* end() { return data+size; }
  16.  
  17.  
  18.   private :
  19.  
  20.   double* data;
  21.   size_t size;
  22. };


 
Je ne m'attarde pas sur les détails, vous etes tous capable de faire ça hein :sol:
Maintenant, on aimerais bien écrire des trucs style :
 

Code :
  1. TableauDouble a(10);
  2. a = 1,2,3,4,5,6,7,8,9,10;


 
Pour initialiser le tableau :) Comment faire ???
Il faut regarder de plus prés cette expression :
 
a = 1,2,3,4,5,6,7,8,9,10;
 
Elle est equivalente à :
 
(((((((((a = 1),2),3),4),5),6),7),8),9),10;
 
Une fois cette précision faite, on peut concevoir que l'expression :
 
(a = 1)
 
va renvoyer une instance d'une classe temporaire - appelons la CommaInit -
qui se verra fournir une surcharge de la virgule :
 

Code :
  1. class CommaInit
  2. {
  3. public :
  4. CommaInit operator,(double x)
  5. {
  6.    *iter = x;
  7.    return CommaInit(iter + 1);
  8. }
  9.   CommaInit(double* iter) : iter_(iter) {}
  10. private:
  11. double* iter;
  12. };


 
Ok, d'accord, ensuite ???
Et bien, surchargons l'operateur = de TableauDouble :
 

Code :
  1. CommaInit operator=( const double& val )
  2. {
  3.   data[0] = val;
  4.   return CommaInit(data + 1);
  5. }


 
Et voila :)
 
Une version plus sécurisée, peut testé iter pour vérifier que l'on ne puisse ecrire :
 

Code :
  1. TableauDouble A(4);
  2. A = 1,2,3,4,5; // ERREUR /!\


 
Exercice :
1) Adaptez ce code pour supporter une syntaxe indépendante du type.  
A savoir permettre l'initialisation en ligne de tableau de char, de float de
complex<double> , etc ...
 
2) Adapter le au conteneur bidimensionel.
 
3) Comment différencier :
 

Code :
  1. // A[i] = val[i]
  2. A = 1,2,3,4,5,6,7,8,9,10;


 
et
 

Code :
  1. // A[i] = 0
  2. A = 0;


 
 
Quelques Liens :
http://osl.iu.edu/~tveldhui/papers/techniques/

Reply

Marsh Posté le 27-04-2004 à 20:30:56   

Reply

Marsh Posté le 27-04-2004 à 20:35:20    

[:drapo]
C'est sur que ça m'était jamais venu à l'idée![:wam]

Reply

Marsh Posté le 27-04-2004 à 20:36:12    

bien vu. mais bon ça reste du bricolage par rapport au futur du C++. attention à ne surcharger , que dans ce genre de cas précis, sinon, c'est une super arme d'ofuscation de code.
 
j'aurais peut être ajouter un contrôle de capacité quand même

Reply

Marsh Posté le 27-04-2004 à 20:38:02    

Taz : oui je sais bien, mais bon, on a le temps pour le nouveau C++ ??

Reply

Marsh Posté le 27-04-2004 à 20:38:18    

joli ;)

Reply

Marsh Posté le 27-04-2004 à 20:38:18    

Taz a écrit :

par rapport au futur du C++.  


:??:

Reply

Marsh Posté le 27-04-2004 à 20:41:35    

joel f a écrit :

Taz : oui je sais bien, mais bon, on a le temps pour le nouveau C++ ??

oh je crois qu'on est plus très loin là

Reply

Marsh Posté le 27-04-2004 à 20:41:59    

Taz a écrit :

oh je crois qu'on est plus très loin là


 
 :sol:

Reply

Marsh Posté le 27-04-2004 à 21:18:49    

Code :
  1. #include <cstddef>
  2. #include <boost/static_assert.hpp>
  3. template<typename T, size_t N>
  4. class Array
  5. {
  6.   T data[N];
  7. public:
  8.   typedef T value_type;
  9.   typedef T* iterator;
  10.   typedef const T* const_iterator;
  11.   iterator begin()
  12.   {
  13.     return data;
  14.   }
  15.   iterator end()
  16.   {
  17.     return data+N;
  18.   }
  19.   const_iterator begin() const
  20.   {
  21.     return data;
  22.   }
  23.   const_iterator end() const
  24.   {
  25.     return data+N;
  26.   }
  27.   template<size_t INDEX>
  28.   struct Comma
  29.   {   
  30.     const Array::iterator it;
  31.     Comma(const Array::iterator i)
  32.       : it(i)
  33.     {
  34.       // NOOP
  35.     }     
  36.     Comma<INDEX+1> operator,(const T &val)
  37.     {
  38.       BOOST_STATIC_ASSERT(INDEX < N);
  39.       *it = val;
  40.       return Comma<INDEX+1>(it+1);
  41.     }
  42.   };
  43.   Comma<1> operator=(const T &val)
  44.   {
  45.     return Comma<0>(begin()), val;
  46.   }
  47. };
  48. #include <algorithm>
  49. #include <iterator>
  50. #include <iostream>
  51. template<typename T, size_t N>
  52. inline std::ostream& operator<<(std::ostream &os, const Array<T, N> &a)
  53. {
  54.   std::copy(a.begin(), a.end(),
  55.     std::ostream_iterator<typename Array<T, N>::value_type>(os, ", " ));
  56.   return os;
  57. }
  58. int main()
  59. {
  60.   typedef Array<int, 5> Vector;
  61.   Vector a;
  62.   std::cout << a << '\n';
  63.   a = 1, 2, 3, 0x42;
  64.   std::cout << a << '\n';
  65.   a = 6;
  66.   std::cout << a << '\n';
  67.   a = 7, 8, 9, 10, 11;
  68.   std::cout << a << '\n';
  69. //   a = 7, 8, 9, 10, 11, 12;
  70. //   std::cout << a << '\n';
  71. }


 
du premier coup sans erreur de compilation !
 
bon évidemment je sais que c'est peut être perfectible, mais bon, pas question d'avoir d'initialisation sans template :o
 
 
edit1: operator= manque un +1
edit2: operator= Comma<0> plutot que de le faire à la main
edit3: Comma manque un petit const


Message édité par Taz le 27-04-2004 à 21:30:15
Reply

Marsh Posté le 27-04-2004 à 21:25:47    

Citation :

Même si l'interet
pour ces posts semblent avoir faibli...


 
Non non.  
 
On sent l'influence du Lisp, là...

Reply

Marsh Posté le 27-04-2004 à 21:25:47   

Reply

Marsh Posté le 27-04-2004 à 21:38:08    


 
si si  :sweat:  
les TPs tout ca , caiplusmieux :o

Reply

Marsh Posté le 27-04-2004 à 21:46:15    

Euh, que ceux-tu dire ?

Reply

Marsh Posté le 27-04-2004 à 21:46:59    

'tain la vache, j'avais pas fait gaffe, si on vire toute la partie affichage, mon g++ dégage tout ce qui sert à rien, c'est à dire tout est considéré comme NOOP, résultat, le programme, il fait rien. superbe méthode pour écrire un int main(){ } en somme

Reply

Marsh Posté le 27-04-2004 à 21:47:16    

el muchacho a écrit :

Euh, que ceux-tu dire ?


 :lol: rien rien ^^ jsuet que c'est l'époque des TP/TD pas des programming tips :p

Reply

Marsh Posté le 27-04-2004 à 22:05:59    

joli :)
 

joel f a écrit :

Même si l'interet
pour ces posts semblent avoir faibli


 
 
je suis toujours aussi interressé :)
 
(d'ailleurs je voudrais bien un petit qqchose sur la construction de stream si qq1 avait le temps :) )


Message édité par blackgoddess le 27-04-2004 à 22:06:20

---------------
-( BlackGoddess )-
Reply

Marsh Posté le 27-04-2004 à 22:09:40    

Citation :

rien rien ^^ jsuet que c'est l'époque des TP/TD pas des programming tips


 
C'est à dire que de mon coté, je suis déjà occupé avec mon petit problème d'algo que j'ai posé (qui n'attire pas non plus les suffrages d'ailleurs); ca doit être un peu trop facile pour Taz et toi, je suppose.
 
ps : au fait, extceptionnel, le lien que tu as donné.


Message édité par el muchacho le 27-04-2004 à 22:17:44
Reply

Marsh Posté le 28-04-2004 à 02:15:06    

biensur, comme nos deux versions utilisent des foward iterator, le concept est généralisable à n'importe quelle séquence. on peut même faire quelque chose de générique. cela dit, la version template n'est elle possible que sur des séquences à taille statique, la vérification des arguments aussi

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed