4.10.1 La partie facile

En ce qui concerne l'ensemble des opérateurs dont la déclaration ne dépend pas de la classe qui les utilisera (comme PVector), il suffit de faire un copier-coller de ce que nous avons fait précédemment.

Pour commencer, on évite les inclusions multiplies :

1
2
3
4
5
#ifndef __PBASE_EXPRESSION_TEMPLATE_ITERATOR_H__
#define __PBASE_EXPRESSION_TEMPLATE_ITERATOR_H__


#endif

Ensuite on rajoute toutes les déclarations qui sont indépendantes de la classe qui les utilisera :

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
///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érales  //
//                                                                    //
////////////////////////////////////////////////////////////////////////

///Modèle de classe pour nos opérateurs unaires
template <class T, int Op>
struct UnaryOp {};

/// Classe de base pour nos opérateurs unaires
template <class T>
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 <class T>
struct UnaryOp<T, Minus> : public UnaryOpBase<T>{
	UnaryOp(T t) : UnaryOpBase<T>(t){}
	inline double operator *(){return -(*UnaryOpBase<T>::It);}
};

///Spécialisation pour les constantes
template <class T>
struct UnaryOp<T, Const> : public UnaryOpBase<T>{
	UnaryOp(T t) : UnaryOpBase<T>(t) {}
	inline void operator ++(){}
	inline double operator *(){return UnaryOpBase<T>::It;}
};

///Modèle de classe pour nos opérateurs binaires
template <class T, class U, int Op>
struct BinaryOp{
	inline double operator *(){return UnaryOpBase<T>::It;}
};

///Classe de base pour nos opérateurs binaires
template <class T, class U>
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 <class T, class U>
struct BinaryOp<T, U, Add> : public BinaryOpBase<T, U>{
	BinaryOp(T I1, U I2) : BinaryOpBase<T, U>(I1, I2){}
	inline double operator *() {return *BinaryOpBase<T, U>::It1 + *BinaryOpBase<T, U>::It2;}
};

///Spécialisation pour la multiplication
template <class T, class U>
struct BinaryOp<T, U, Mult> : public BinaryOpBase<T, U>{
	BinaryOp(T I1, U I2) : BinaryOpBase<T, U>(I1, I2){}
	inline double operator *() {return *BinaryOpBase<T, U>::It1 * *BinaryOpBase<T, U>::It2;}
};

///Spécialisation pour la division
template <class T, class U>
struct BinaryOp<T, U, Sub> : public BinaryOpBase<T, U>{
	BinaryOp(T I1, U I2) : BinaryOpBase<T, U>(I1, I2){}
	inline double operator *() {return *BinaryOpBase<T, U>::It1 - *BinaryOpBase<T, U>::It2;}
};

///Spécialisation pour la division
template <class T, class U>
struct BinaryOp<T, U, Div> : public BinaryOpBase<T, U>{
	BinaryOp(T I1, U I2) : BinaryOpBase<T, U>(I1, I2){}
	inline double operator * () {return *BinaryOpBase<T, U>::It1 / *BinaryOpBase<T, U>::It2;}
};

////////////////////////////////////////////////////////////////////////////
//                                                                        //
//   fonctions qui permettent de simplifier la surcharge des opérateurs   //
//                                                                        //
////////////////////////////////////////////////////////////////////////////

///Simplification de la surcharge de l'addition
template <class T, class U>
inline BinaryOp<T, U, Add> MakeAdd(const T& t, const U& u){
	return BinaryOp<T, U, Add>(t, u);
}

///Simplification de la surcharge de la soustraction
template <class T, class U>
inline BinaryOp<T, U, Sub> MakeSub(const T& t, const U& u){
	return BinaryOp<T, U, Sub>(t, u);
}

///Simplification de la surcharge de la multiplication
template <class T, class U>
inline BinaryOp<T, U, Mult> MakeMult(const T& t, const U& u){
	return BinaryOp<T, U, Mult>(t, u);
}

///Simplification de la surcharge de la division
template <class T, class U>
inline BinaryOp<T, U, Div> MakeDiv(const T& t, const U& u){
	return BinaryOp<T, U, Div>(t, u);
}

///Simplification de la surcharge de la négation
template <class T>
inline UnaryOp<T, Minus> MakeMinus(const T& t){
	return UnaryOp<T, Minus>(t);
}

///Simplification de la surcharge de la constante
template <class T>
inline UnaryOp<T, Const> MakeConst(const T& t){
	return UnaryOp<T, Const>(t);
}

//////////////////////////////////////////
//                                      //
//       Surcharge des opérateurs       //
//                                      //
//////////////////////////////////////////

//////////////////////////////////////////////////////////////////
//                                                              //
//       Surcharge des opérateurs pour des types abstraits      //
//                                                              //
//////////////////////////////////////////////////////////////////

///Surcharge de l'opérateur + pour deux types abstraits
template <class T, class U>
BinaryOp<T, U, Add> operator +(const T& v1, const U& v2){
	return MakeAdd(v1, v2);
}

///Surcharge de l'opérateur - pour deux types abstraits
template <class T, class U>
BinaryOp<T, U, Sub> operator - (const T& v1, const U& v2){
	return MakeSub(v1, v2);
}

// Surcharge de l'opérateur - pour un type abstrait
template <class T>
UnaryOp<T, Minus> 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éjà bien pour faire des tests)
template <class T>
BinaryOp<T, UnaryOp<double, Const>, 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éjà bien pour faire des tests)
template <class T>
BinaryOp<UnaryOp<double, Const>, T, Mult> operator * (double d, const T& v1){
	return MakeMult(MakeConst(d), v1);
}

Passons à la partie un peut plus délicate.