Bonsoir !

Je m'essaye depuis peu aux expression templates pour essayer de créer une petite classe pour gérer les vecteurs, plutôt dans un but didactique dans un premier temps, après je ferai des tests de performances voir si ça vaut le coup.

Bref, plutôt que d'embêter à chaque fois loulou avec des MP, je vais poster ici cette fois .

Donc j'ai une classe SVec3 minimale :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <boost/array.hpp>
 
template <typename T> // Paramètre template
class SVec3
{
   public:
      // Plusieurs constructeurs/destructeur
      SVec3 ();
      SVec3 (const T &, const T &, const T &);
      SVec3 (const SVec3 <T> &);
      ~SVec3 ();
 
      // Surcharges de l'opérateur [] en lecture et en écriture
      T operator [] (const size_t) const;
      T & operator [] (const size_t);
 
   private:
      boost::array <T, 3> values; // Tableau statique contenant trois éléments
};
Je ne vous met pas toutes les définitions, juste le constructeur de copies :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
// Constructeur de copie
template <typename T>
SVec3<T>::SVec3 (const SVec3 <T> & vec)
   : values (vec)
{
}
Ca marche parfaitement bien si j'instancie des SVec3 normalement. Par exemple SVec3 <double> vec1 (1.0, 1.0, 1.0); SVec3 <double> vec2 (vec1);

Là ça marche bien.

Maintenant je crée une classe Vec3 pour créer mes arbres (désolé si ma terminologie n'est pas bonne, j'essaye surtout de comprendre comment ça fonctionne, je crois que ça commence à rentrer mais pas encore la terminologie :p) :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "SVec3.hpp" // Inclut le fichier d'en-tête de la classe SVec3
 
 
template <typename T, typename Expr = SVec3 <T> >
class Vec3
{
   public:
      // Plusieurs constructeurs/destructeur
      Vec3 ();
      Vec3 (const T &, const T &, const T &);
      Vec3 (Vec3 &);
      ~Vec3 ();
 
      // Surcharges de l'opérateur [] en lecture et en écriture
      T operator [] (const size_t) const;
      T & operator [] (const size_t);
 
   private:
      Expr myExpression; // Expression template. Par défaut : SVec3 <T>
};
 
// Constructeur par défaut. Appelle le constructeur de myExpression. Par exemple, si
// l'appel à Vec3 est celui-ci : Vec3 <double>, le deuxième paramètre template sera,
// par défaut, SVec3 <double>, et donc le constructeur de SVec3 <double> sera appelé
template <typename T, typename Expr>
Vec3 <T, Expr>::Vec3 ()
   : myExpression ()
{
}
 
// Constructeur. Celui-ci permet d'initialiser un vecteur avec trois valeurs
template <typename T, typename Expr>
Vec3 <T, Expr>::Vec3 (const T & x, const T & y, const T & z)
   : myExpression (x, y, z)
{
}
Après avoir fait joujou avec quelqeus constructeurs (je sais qu'il manque le constructeur pour pouvoir instancié un Vec3 à partir une expression telle que A_Add <Vec3<T>, Vec3<T> >, je l'ai pas encore mise), si je fais :

Vec3 <double> monVecteur; et que je regarde dans le profiler, ça m'instancie bien Vec3 <double>, puis ça m'appelle bien le constructeur de SVec3 puisque c'est le paramètre template par défaut pour Expr, ce qui m'initialise bien toutes mes valeurs à 0. Ca marche également si je fais :

Vec3 <double> monVecteur (1.0, 1.0, 1.0);

Le problème vient de mon constructeur de copie. Idéalement, je voudrais faire ceci :

Vec3 <double> monVecteur (1.0, 1.0, 1.0);
Vec3 <double> vec2 (monVecteur);

Et donc de ce fait j'ai codé mon constructeur comme ceci :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
template <typename T, typename Expr>
Vec3 <T, Expr>::Vec3 (Vec3 <T, Expr> & vec)
   : myExpression (vec.myExpression)
{
}
D'après moi, le deuxième appel est l'équivalent de ceci :

Vec3 <double, SVec3 <double> > vec2 (monVecteur);

// Constructeur :
Vec3 <T, Expr>::Vec3 <Vec3 <double, SVec3 <double> > & vec, ou SVec3 <double> est myExpression. Ca me paraissait logique donc d'écrire myExpression (vec.myExpression), ce qui, d'après moi aurait comme effet :

SVec3 <double> (vec.SVec3 <double>)...

Or le compilo n'a pas l'air de l'entendre comme ça :

Vec3.hpp:46: instantiated from `Vec3<T, Expr>::Vec3(Vec3<T, Expr>&) [with T = double, Expr = SVec3<double>]'
SVec3.hpp:51: error: no matching function for call to `boost::array<double, 3u>::array(const SVec3<double>&)'
array.hpp:43: note: candidates are: boost::array<double, 3u>::array()
array.hpp:43: note: boost::array<double, 3u>::array(const boost::array<double, 3u>&)
:: === Build finished: 4 errors, 0 warnings ===
J'avoue ne pas tellement comprendre, car même le message d'erreur semble me donner raison avec Expr = SVec3 <double>... Donc myExpression (vec.myExpression) == myExpression(vec.SVec3 <double> ).

J'espère que je suis assez clair, sinon je peux toujours développer plus.

Merci de votre aide !