Bonjour,
Je suis face à un problème d'ordre général à propos du downcasting. Généralement, je pars du principe que downcaster est synonyme d'un problème de conception, or dans mon cas, je ne trouve que peu d'alternatives et pas spécialement attrayantes.
J'implémente un compilateur, on doit donc représenter les types du langage source : tableau, structure, … On peut donc faire hériter les types de la classe Type.
Or à un moment ou à un autre il faudra comparer ces types, par surcharge de l'opérateur ==.
On peut dès lors avoir deux solutions :
Sans variant :
Avec variant :
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 class Type { public: virtual bool operator==(const shared_ptr<Type>& type) =0; }; class Structure : Type { public: virtual bool operator==(const shared_ptr<Type>& type) { shared_ptr<Structure> toCompare = dynamic_pointer_cast<Structure>(type); if(toCompare) { // Ok comparaison un par un des champs de la classe. } return false; } }; // Dans le code if(!(type1 == type2)) { message_error_type(type1, type2); }
De ces deux solutions, je préfère encore la variant, j'évite ainsi le dynamic cast, et il me semble que c'est plus propre. Notons tout de même que les types peuvent se contenir entre eux (array de structure, tableau multidimension), donc l'usage du recursive_wrapper des variants semblent inévitables.
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 class Type { public: boost::variant<Structure, ...> value; }; class Structure { public: bool operator==(const shared_ptr<Structure>& type) { // Ok comparaison un par un des champs de la classe. } }; class BinaryVisitorType : public boost::static_visitor<> { public: template <typename T> void operator()(const T& type1, const T& type2) { if(!(type1 == type2)) message_error_type(type1, type2); } template <typename T1, typename T2> void operator()(const T1& type1, const T2& type2) { message_error_type(type1, type2); } };
Mais je ne suis guère satisfait car j'aurais aimé implémenter une vraie relation EST-UN tout en gardant les avantages de la variante.
Comment faire ça proprement ?
Merci d'avance.
Partager