#ifndef __PBASE_EXPRESSION_TEMPLATE_ITERATOR_H__ #define __PBASE_EXPRESSION_TEMPLATE_ITERATOR_H__ ///Les opérateurs des expressions template générales enum Operators{ Add, // addition Sub, // soustraction Mult, // multiplication Div, // division Plus, // + unaire Minus, // - unaire Const // Constante }; //////////////////////////////////////////////////////////////////////// // // // Les opérateurs unitaires de nos expressions template génératles // // // //////////////////////////////////////////////////////////////////////// ///Modèle de classe pour nos opérateurs unaires template struct UnaryOp {}; /// Classe de base pour nos opérateurs unaires template struct UnaryOpBase{ UnaryOpBase(T t) : It(t) {} inline void operator ++(){++It;} T It; }; ///////////////////////////////////////////////////////////// // // // Spécialisation des UnaryOp pour tous les opérateurs // // // ///////////////////////////////////////////////////////////// ///Spécialisation pour le moins unaire template struct UnaryOp : public UnaryOpBase{ UnaryOp(T t) : UnaryOpBase(t){} inline double operator *(){return -(*UnaryOpBase::It);} }; ///Spécialisation pour les constantes template struct UnaryOp : public UnaryOpBase{ UnaryOp(T t) : UnaryOpBase(t) {} inline void operator ++(){} inline double operator *(){return UnaryOpBase::It;} }; ///Modèle de classe pour nos opérateurs binaires template struct BinaryOp{ inline double operator *(){return UnaryOpBase::It;} }; ///Classe de base pour nos opérateurs binaires template struct BinaryOpBase{ BinaryOpBase(T I1, U I2) : It1(I1), It2(I2) {} inline void operator ++(){++It1; ++It2;} inline double operator *(){return *It1 + *It2;} T It1; U It2; }; ////////////////////////////////////////////////////////////// // // // Spécialisation des BinaryOp pour tous les opérateurs // // // ////////////////////////////////////////////////////////////// ///Spécialisation pour l'addition template struct BinaryOp : public BinaryOpBase{ BinaryOp(T I1, U I2) : BinaryOpBase(I1, I2){} inline double operator *() {return *BinaryOpBase::It1 + *BinaryOpBase::It2;} }; ///Spécialisation pour la multiplication template struct BinaryOp : public BinaryOpBase{ BinaryOp(T I1, U I2) : BinaryOpBase(I1, I2){} inline double operator *() {return *BinaryOpBase::It1 * *BinaryOpBase::It2;} }; ///Spécialisation pour la division template struct BinaryOp : public BinaryOpBase{ BinaryOp(T I1, U I2) : BinaryOpBase(I1, I2){} inline double operator *() {return *BinaryOpBase::It1 - *BinaryOpBase::It2;} }; ///Spécialisation pour la division template struct BinaryOp : public BinaryOpBase{ BinaryOp(T I1, U I2) : BinaryOpBase(I1, I2){} inline double operator * () {return *BinaryOpBase::It1 / *BinaryOpBase::It2;} }; //////////////////////////////////////////////////////////////////////////// // // // fonctions qui permettent de simplifier la surcharge des opérateurs // // // //////////////////////////////////////////////////////////////////////////// ///Simplification de la surchage de l'addition template inline BinaryOp MakeAdd(const T& t, const U& u){ return BinaryOp(t, u); } ///Simplification de la surchage de la soustraction template inline BinaryOp MakeSub(const T& t, const U& u){ return BinaryOp(t, u); } ///Simplification de la surchage de la multiplication template inline BinaryOp MakeMult(const T& t, const U& u){ return BinaryOp(t, u); } ///Simplification de la surchage de la division template inline BinaryOp MakeDiv(const T& t, const U& u){ return BinaryOp(t, u); } ///Simplification de la surchage de la négation template inline UnaryOp MakeMinus(const T& t){ return UnaryOp(t); } ///Simplification de la surchage de la constante template inline UnaryOp MakeConst(const T& t){ return UnaryOp(t); } ////////////////////////////////////////// // // // Surcharge des opérateurs // // // ////////////////////////////////////////// ////////////////////////////////////////////////////////////////// // // // Surcharge des opérateurs pour des types abstraits // // // ////////////////////////////////////////////////////////////////// ///Surcharge de l'opérateur + pour deux types abstraits template BinaryOp operator +(const T& v1, const U& v2){ return MakeAdd(v1, v2); } ///Surcharge de l'opérateur - pour deux types abstraits template BinaryOp operator - (const T& v1, const U& v2){ return MakeSub(v1, v2); } // Surcharge de l'opérateur - pour un type abstrait template UnaryOp operator - (const T& v1){ return MakeMinus(v1); } ///Surcharge de l'opérateur * pour un type abstrait à gauche et un double (en dur je sais, mais c'est déja bien pour faire des tests) template BinaryOp, Mult> operator * (const T& v1, double d){ return MakeMult(v1, MakeConst(d)); } ///Surcharge de l'opérateur * pour un type abstrait à droite et un double (en dur je sais, mais c'est déja bien pour faire des tests) template BinaryOp, T, Mult> operator * (double d, const T& v1){ return MakeMult(MakeConst(d), v1); } ///////////////////////////////////////////////////////////////////////////////////////////////////// // // // Macros qui définissent la surcharge des opérateurs pour un type quelconque et son itérateur // // // ///////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////// // // // Ce qui conserne l'addition // // // //////////////////////////////////// //Macro qui permet de définir la surchage de l'opérateur + à gauche pour un type définit, et son iterateur constant /* Le TYPE peut être : PVector * Le TYPECONSTITERATOR peut être : PVector::ConstIterator */ #define PSURCHAGE_IT_TYPE_OP_ADD_LEFT(TYPE,TYPECONSTITERATOR) template BinaryOp operator +(const TYPE& v1, const T& v2){return MakeAdd(v1.begin(), v2);} //Macro qui permet de définir la surchage de l'opérateur + à droite pour un type définit, et son iterateur constant /* Le TYPE peut être : PVector * Le TYPECONSTITERATOR peut être : PVector::ConstIterator */ #define PSURCHAGE_IT_TYPE_OP_ADD_RIGHT(TYPE,TYPECONSTITERATOR) template BinaryOp operator +(const T& v1, const TYPE& v2){return MakeAdd(v1, v2.begin());} //Macro qui permet de définir la surchage de l'opérateur + pour deux types définis, et leur iterateur constant /* Le TYPE peut être : PVector * Le TYPECONSTITERATOR peut être : PVector::ConstIterator */ #define PSURCHAGE_IT_TYPE_OP_ADD_TYPE(TYPE,TYPECONSTITERATOR) BinaryOp operator +(const TYPE& v1, const TYPE& v2){return MakeAdd(v1.begin(), v2.begin());} ///////////////////////////////////////// // // // Ce qui conserne la soustraction // // // ///////////////////////////////////////// //Macro qui permet de définir la surchage de l'opérateur - pour deux types définis, et leur iterateur constant /* Le TYPE peut être : PVector * Le TYPECONSTITERATOR peut être : PVector::ConstIterator */ #define PSURCHAGE_IT_TYPE_OP_SUB_TYPE(TYPE,TYPECONSTITERATOR) BinaryOp operator - (const TYPE& v1, const TYPE& v2){return MakeSub(v1.begin(), v2.begin());} /////////////////////////////////////////// // // // Ce qui conserne la multiplication // // // /////////////////////////////////////////// //Macro qui permet de définir la surchage de l'opérateur * à gauche pour un type définit, et son iterateur constant /* Le TYPE peut être : PVector * Le TYPECONSTITERATOR peut être : PVector::ConstIterator */ #define PSURCHAGE_IT_TYPE_OP_MULT_LEFT(TYPE,TYPECONSTITERATOR) BinaryOp, Mult> operator * (const TYPE& v1, double d){return MakeMult(v1.begin(), MakeConst(d));} //Macro qui permet de définir la surchage de l'opérateur * à droite pour un type définit, et son iterateur constant /* Le TYPE peut être : PVector * Le TYPECONSTITERATOR peut être : PVector::ConstIterator */ #define PSURCHAGE_IT_TYPE_OP_MULT_RIGHT(TYPE,TYPECONSTITERATOR) BinaryOp, TYPECONSTITERATOR, Mult> operator * (double d, const TYPE& v1){return MakeMult(MakeConst(d), v1.begin());} //Macro qui permet de définir la surchage de l'opérateur / à droite pour un scalaire (ici un double), et son iterateur constant /* Le TYPE peut être : PVector * Le TYPECONSTITERATOR peut être : PVector::ConstIterator */ #define PSURCHAGE_IT_TYPE_OP_DIV_SCAL(TYPE,TYPECONSTITERATOR) BinaryOp, Div> operator / (const TYPE& v1, double d){return MakeDiv(v1.begin(), MakeConst(d));} //Macro qui permet de définir la surchage de l'opérateur - (pour définir l'opposé d'un type), et son iterateur constant /* Le TYPE peut être : PVector * Le TYPECONSTITERATOR peut être : PVector::ConstIterator */ #define PSURCHAGE_IT_TYPE_OP_MINUS(TYPE,TYPECONSTITERATOR) UnaryOp operator - (const TYPE& v1){return MakeMinus(v1.begin());} //////////////////////////////////////////////////////////////////////////////////////////// // // // Et maintenant une grosse macro de fainéant qui permet de tout faire d'un seul coup // // // //////////////////////////////////////////////////////////////////////////////////////////// //Macro qui permet de définir la surchage de tout les opérateurs pour un type, et son iterateur constant /* Le TYPE peut être : PVector * Le TYPECONSTITERATOR peut être : PVector::ConstIterator */ #define PSURCHAGE_IT_TYPE_ALL_OP(TYPE,TYPECONSTITERATOR) PSURCHAGE_IT_TYPE_OP_ADD_LEFT(TYPE,TYPECONSTITERATOR) \ PSURCHAGE_IT_TYPE_OP_ADD_RIGHT(TYPE,TYPECONSTITERATOR) \ PSURCHAGE_IT_TYPE_OP_ADD_TYPE(TYPE,TYPECONSTITERATOR) \ PSURCHAGE_IT_TYPE_OP_SUB_TYPE(TYPE,TYPECONSTITERATOR) \ PSURCHAGE_IT_TYPE_OP_MULT_LEFT(TYPE,TYPECONSTITERATOR) \ PSURCHAGE_IT_TYPE_OP_MULT_RIGHT(TYPE,TYPECONSTITERATOR) \ PSURCHAGE_IT_TYPE_OP_DIV_SCAL(TYPE,TYPECONSTITERATOR) \ PSURCHAGE_IT_TYPE_OP_MINUS(TYPE,TYPECONSTITERATOR) #endif