Bonjour.
Je dois stocker dans un conteneur des objets polymorphiques.
Ce qui m'oblige à utiliser des pointeurs.
Les classes en question n'ont pas de constructeur par défaut et ne sont ni copiables ni assignables.
Mais elles sont déplaçables et swappables.
Vu que le conteneurs est censé stocker les objets, il est responsable de leur création et de leur destruction.
J'utilise donc std::unique_ptr.
Le problème, c'est d'arriver à créer les bonnes instances d'objet.
La première idée qui m'est venue fut de faire une fonction clone dont le but est créer une copie par déplacement, allouée dynamiquement, à redéfinir dans les classes filles.
(Je sais, le nom n'est pas très bien choisi...)
Sauf qu'au final, toutes les redéfinitions auront la même tête, il y aura juste de nom de la classe (après new) qui changera.
Ça fait duplication de code...
Bon, voyons ce que les templates peuvent m'apporter...
Je me disais que la fonction membre statique serait capable de déterminer le type réel de l'objet x.
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 class A { private: template <class T> static std::unique_ptr<A> clone(T&& x) { return std::unique_ptr( new T(std::move(x)) ); } public: std::unique_ptr<A> clone() { return clone(std::move(*this)); } };
Sauf que vu que je l'appelle depuis un A, elle ne peut pas...
Commet cela, ça fonctionne déjà mieux.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 class A { public: template <class T> static std::unique_ptr<A> clone(A&& x) { typedef typename std::remove_reference<T>::type type; return std::unique_ptr( new type(std::move(x)) ); } };
J'ai juste oublié que lors de l'insertion :
je passe encore via un A.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12 class container : private std::vector< std::unique_ptr<A> > { private: typedef std::vector< std::unique_ptr<A> > _base; public: void insert(A&& x) { _base::push_back( A::clone(std::move(x)) ); } };
L'autre solution que je vois, c'est de rendre la fonction insert template, et d'y créer la copie.
Dans ce cas, on pourra se rendre compte à la compilation si l'on essaie d'insérer un objet qui n'hérite pas de A ?
Si vous avez d'autres suggestions, je suis preneur...
Partager