2010-03-17 11 views
11

Voici le scénario: Je voudrais avoir une classe hôte qui peut avoir un nombre variable de mixins (pas trop difficile avec des modèles variadiques - voir par exemple http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.103.144). Cependant, j'aimerais aussi que les mixins soient paramétrés par la classe hôte, afin qu'ils puissent se référer à ses types publics (en utilisant l'idiome de CRTP). Le problème se pose lorsque vous essayez de mélanger les deux - la syntaxe correcte ne me semble pas claire. Par exemple, le code suivant ne peut pas compiler avec g ++ 4.4.1:Mixins, modèles variadiques, et CRTP en C++

template <template<class> class... Mixins> 
class Host : public Mixins<Host<Mixins>>... { 
    public: 
    template <class... Args> 
    Host(Args&&... args) : Mixins<Host>(std::forward<Args>(args))... {} 
}; 

template <class Host> struct Mix1 {}; 

template <class Host> struct Mix2 {}; 

typedef Host<Mix1, Mix2> TopHost; 
TopHost *th = new TopHost(Mix1<TopHost>(), Mix2<TopHost>()); 

Avec l'erreur:

tst.cpp: In constructor ‘Host<Mixins>::Host(Args&& ...) [with Args = Mix1<Host<Mix1, Mix2> >, Mix2<Host<Mix1, Mix2> >, Mixins = Mix1, Mix2]’: 

tst.cpp:33: instantiated from here 

tst.cpp:18: error: type ‘Mix1<Host<Mix1, Mix2> >’ is not a direct base of ‘Host<Mix1, Mix2>’ 

tst.cpp:18: error: type ‘Mix2<Host<Mix1, Mix2> >’ is not a direct base of ‘Host<Mix1, Mix2>’ 

Quelqu'un at-il une expérience réussie mélange des modèles variadique avec CRTP?

Répondre

6

Ce qui suit semble fonctionner. J'ai ajouté Mixins... dans les classes mixin héritées qui étendent le pack de paramètres inplace. En dehors du corps du modèle Host, tous les paramètres de modèle de Host doivent être spécifiés afin que Mixins... serve le but. À l'intérieur du corps, juste Host suffit pas besoin d'épeler tous ses paramètres de modèle. Une sorte de petite main.

#include <utility> 

template <template<class> class... Mixins> 
class Host : public Mixins<Host<Mixins...>>... 
{ 
    public: 
    Host(Mixins<Host>&&... args) : Mixins<Host>(std::forward<Mixins<Host>>(args))... {} 
}; 

template <class Host> struct Mix1 {}; 
template <class Host> struct Mix2 {}; 

int main (void) 
{ 
    typedef Host<Mix1, Mix2> TopHost; 
    delete new TopHost(Mix1<TopHost>(), Mix2<TopHost>()); 
} 
+0

Je l'ai révisé pour inclure le constructeur templatisé. modèle Hôte (Args && ... args): Mixins (std :: forward > (args)) ... {} – Sumant

+0

Merci, Sumant. Votre suggestion est logique, mais ne fonctionne pas pour moi. Quelle version du compilateur utilisez-vous? J'ai copié et collé ce code et lors de la compilation, j'ai obtenu: tst2.cpp: Dans la fonction 'int main()': tst2.cpp: 16: erreur: aucune fonction correspondante pour l'appel à 'Host : : Hôte (Mix1 >, Mix2 >) ' tst2.cpp: 7: note: les candidats sont: Hôte :: Hôte (Mixins > && ...) [avec Mixins = Mix1, Mix2] tst2.cpp: 5: note: Hôte :: Hôte (const Hôte &) – Eitan

+0

Oh, j'ai raté votre révision. Cela corrige l'erreur "aucune fonction correspondante", mais explose avec "erreur de compilation interne" :) Encore une fois, quel compilateur utilisez-vous? – Eitan