Je cherche à factoriser au maximum du code partagé entre plusieurs classes qui définissent des machines à états, sans utiliser d'héritage et de méthodes virtuelles. J'ai donc regardé du côté des templates, et j'en suis arrivé à me dire que le CRTP pouvait être une bonne idée pour ce faire. J'ai donc écrit un code qui ressemble vaguement à ça :
Le problème est que ça ne compile pas :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 template<class T> class A { public: typename T::toto val; int a[T::nbelem]; }; class B : public A<B> { public: enum toto { a, b, c, nbelem }; toto f() { return val; } };
Je peux contourner ce problème en "sortant" la définition de mon enum dans une autre classe, et en écrivant le code suivant (je n'ai pas touché à A) :test.cxx: In instantiation of ‘A<B>’:
test.cxx:16: instantiated from here
test.cxx:5: error: invalid use of incomplete type ‘class B’
test.cxx:15: error: forward declaration of ‘class B’
test.cxx:6: error: incomplete type ‘B’ used in nested name specifier
test.cxx:6: error: array bound is not an integer constant
test.cxx: In member function ‘B::toto B::f()’:
test.cxx:19: error: ‘val’ was not declared in this scope
Ça me convient bien, et je pense que je vais faire comme ça. Par contre, j'aimerai bien comprendre pourquoi le premier code ne compile pas. Si quelqu'un a une explication...
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11 class paramB { public: enum toto { a, b, c, nbelem }; }; class B : public A<paramB> { public: paramB::toto f() { return val; } };
Partager