2010-03-17 36 views
11

Ecco lo scenario: mi piacerebbe avere una classe host che può avere un numero variabile di mixin (non troppo difficile con i modelli variadic - si veda ad esempio http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.103.144). Tuttavia, mi piacerebbe anche che i mixin fossero parametrizzati dalla classe host, in modo che possano riferirsi ai suoi tipi pubblici (usando l'idioma CRTP). Il problema sorge quando si tenta di mescolare i due - la sintassi corretta non è chiara per me. Ad esempio, il seguente codice non riesce a compilare con g ++ 4.4.1:Mixin, modelli variadici e CRTP in 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>()); 

con l'errore:

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>’ 

Qualcuno ha esperienza di successo di miscelazione modelli variadic con CRTP?

risposta

6

Quanto segue sembra funzionare. Ho aggiunto Mixins... nelle classi di mixin ereditate che espande il parametro pack inplace. Al di fuori del corpo del modello Host, è necessario specificare tutti i parametri del modello di Host in modo che lo scopo sia Mixins.... All'interno del corpo, è sufficiente solo Host senza dover specificare tutti i parametri del modello. Tipo di una mano corta.

#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

L'ho modificato per includere il costruttore templatizzato. template Host (Args && ... args): Mixins (std :: forward > (args)) ... {} – Sumant

+0

Grazie, Sumant. Il tuo suggerimento ha senso, ma non riesce a funzionare in qualche modo per me. Quale versione del compilatore stai usando? Ho copiato e incollato questo codice e durante la compilazione, ottenuto: tst2.cpp: nella funzione 'int main()': tst2.cpp: 16: errore: nessuna funzione di corrispondenza per la chiamata a 'Host : : Host (Mix1 >, Mix2 >) ' tst2.cpp: 7: nota: i candidati sono: Host :: Host (Mixins > && ...) [con Mixins = Mix1, Mix2] tst2.cpp: 5: nota: Host :: Host (host const &) – Eitan

+0

Oh, ho perso la revisione. Questo risolve l'errore "nessuna corrispondenza", ma esplode con "Errore interno del compilatore" :) Quindi, di nuovo, quale compilatore stai usando? – Eitan

Problemi correlati