4.10.4 Le nouveau 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
#include <iostream>

#define SIZE_PVECTOR_TAB 50

#include "PBaseExpressionTemplateIterator.h"

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 =
/**	@param expr : expression template ou le calcul est définit sou forme d'arbre par le compilateur
 * 	@return PVector calculé comme il faut
 * 	C'est un méthode qui permet de transformer une expression de calcul compliquée en une expression en C avec une boucle qui poura éventuellement vectorisée
 * 	si cela est possible ou parallèlisée avec OpenMP sans que le programmeur ne se soit cassé la tête
*/
template <class T>
const PVector& PVector::operator = (T expr){
	//je ne suis pas convaincu que l'on puisse faire du OpenMP avec une boucle for définie comme ça
	for(Iterator i = begin(); i != end(); ++i, ++expr){
		*i = *expr;
	}
	return *this;
}

//Surcharge des opérateurs pour le PVector
PSURCHAGE_IT_TYPE_ALL_OP(PVector,PVector::ConstIterator)
//cette macro est équivalente à toutes celles ci dessous

// PSURCHAGE_IT_TYPE_OP_ADD_LEFT(PVector,PVector::ConstIterator)
// PSURCHAGE_IT_TYPE_OP_ADD_RIGHT(PVector,PVector::ConstIterator)
// PSURCHAGE_IT_TYPE_OP_ADD_TYPE(PVector,PVector::ConstIterator)
// PSURCHAGE_IT_TYPE_OP_SUB_TYPE(PVector,PVector::ConstIterator)
// PSURCHAGE_IT_TYPE_OP_MULT_LEFT(PVector,PVector::ConstIterator)
// PSURCHAGE_IT_TYPE_OP_MULT_RIGHT(PVector,PVector::ConstIterator)
// PSURCHAGE_IT_TYPE_OP_DIV_SCAL(PVector,PVector::ConstIterator)
// PSURCHAGE_IT_TYPE_OP_MINUS(PVector,PVector::ConstIterator)

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 = 1.0 * (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;
}

//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>;


Le fichier main.cpp est beaucoup plus court qu'avant, et la génération des opérateurs spécialisés pour une classe donnée (avec un itérateur) est beaucoup plus simple.

Notez que c'est la macro à la ligne 46 qui permet de tout faire, à partir du moment où l'opérateur = est définit pour le PVector avec un type template. Ce qui rend ces expressions templates très simplement réutilisables.