4.7 Le fichier main.cpp complet

Voici le fichier main.cpp :

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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#include <iostream>

#define SIZE_PVECTOR_TAB 50

struct PVector{
	// Définition des types iterateurs
	typedef double* Iterator;
	typedef const double* ConstIterator;

	// Fonctions de récupération des itérateurs de début et de fin
	Iterator begin(){return p_elements;}
	Iterator end(){return p_elements + SIZE_PVECTOR_TAB;}
	ConstIterator begin()const{return p_elements;}
	ConstIterator end()const{return p_elements + SIZE_PVECTOR_TAB;}
	
	void setValue(double val){
		for(Iterator it = begin(); it != end(); ++it){
			*it = val;
		}
	}
	
	template<class T>
	const PVector& operator = (T expr);
	
	// Et enfin les données
	double p_elements[SIZE_PVECTOR_TAB];
};

//Surcharge de l'opérateur d'affectation =
template <class T>
const PVector& PVector::operator = (T expr){
	for(Iterator i = begin(); i != end(); ++i, ++expr){
		*i = *expr;
	}
	return *this;
}

//Nos opérateurs
enum Operators{
	Add,   // addition
	Sub,   // soustraction
	Mult,  // multiplication
	Div,   // division
	Plus,  // + unaire
	Minus, // - unaire
	Const  // Constante
};


//des opérateurs unitaires

// 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 pour le moins unaire - nous devrons spécialiser nos classes pour chaque opérateur
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 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;}
};

//arbre générer par le compilateur

// BinaryOp<BinaryOp<PVector::const_iterator, UnaryOp<double,Const>,Div>,BinaryOp<BinaryOp<PVector::const_iterator,PVector::const_iterator,Add>,UnaryOp<double,Const>,Mult>,Minus>;

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

template <class T, class U>
inline BinaryOp<T, U, Add> MakeAdd(const T& t, const U& u){
	return BinaryOp<T, U, Add>(t, u);
}

template <class T, class U>
inline BinaryOp<T, U, Sub> MakeSub(const T& t, const U& u){
	return BinaryOp<T, U, Sub>(t, u);
}

template <class T, class U>
inline BinaryOp<T, U, Mult> MakeMult(const T& t, const U& u){
	return BinaryOp<T, U, Mult>(t, u);
}

template <class T, class U>
inline BinaryOp<T, U, Div> MakeDiv(const T& t, const U& u){
	return BinaryOp<T, U, Div>(t, u);
}

template <class T>
inline UnaryOp<T, Minus> MakeMinus(const T& t){
	return UnaryOp<T, Minus>(t);
}

template <class T>
inline UnaryOp<T, Const> MakeConst(const T& t){
	return UnaryOp<T, Const>(t);
}


//Surcharge des opérateurs

//Surcharge de l'opérateur +

template <class T, class U>
BinaryOp<T, U, Add> operator +(const T& v1, const U& v2){
	return MakeAdd(v1, v2);
}

template <class T>
BinaryOp<PVector::ConstIterator, T, Add> operator +(const PVector& v1, const T& v2){
	return MakeAdd(v1.begin(), v2);
}

template <class T>
BinaryOp<T, PVector::ConstIterator, Add> operator +(const T& v1, const PVector& v2){
	return MakeAdd(v1, v2.begin());
}

BinaryOp<PVector::ConstIterator, PVector::ConstIterator, Add> operator +(const PVector& v1, const PVector& v2){
	return MakeAdd(v1.begin(), v2.begin());
}

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

BinaryOp<PVector::ConstIterator, PVector::ConstIterator, Sub> operator - (const PVector& v1, const PVector& v2){
	return MakeSub(v1.begin(), v2.begin());
}

//Surcharge de l'opérateur *

template <class T>
BinaryOp<T, UnaryOp<double, Const>, Mult> operator * (const T& v1, double d){
	return MakeMult(v1, MakeConst(d));
}

BinaryOp<PVector::ConstIterator, UnaryOp<double, Const>, Mult> operator * (const PVector& v1, double d){
	return MakeMult(v1.begin(), MakeConst(d));
}

//Surcharge de l'opéateur /

BinaryOp<PVector::ConstIterator, UnaryOp<double, Const>, Div> operator / (const PVector& v1, double d){
	return MakeDiv(v1.begin(), MakeConst(d));
}

// Surcharge de l'opérateur - (pour -PVector)

template <class T>
UnaryOp<T, Minus> operator - (const T& v1){
	return MakeMinus(v1);
}

UnaryOp<PVector::ConstIterator, Minus> operator - (const PVector& v1){
	return MakeMinus(v1.begin());
}

using namespace std;

int main(int argc, char **argv) {
	cout << "Hello, world!" << endl;
	
	PVector v1, v2, v3, v4;
	
	v1.setValue(1.0);
	v2.setValue(1.0);
	v3.setValue(1.0);
	
	v4 = (v1 / 2.0) - (v2 + v3) * 2.0;
	
	cout << "v4 = (" << v4.p_elements[0] << ", " << v4.p_elements[1] << ", " << v4.p_elements[2] << ")" << endl;
	cout << "On doit avoir (-3.5, -3.5, -3.5)" << endl;
	
	return 0;
}