2010-03-17 24 views
11

Aquí está el escenario: me gustaría tener una clase de host que pueda tener un número variable de mixins (no demasiado difícil con plantillas variadic - vea por ejemplo http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.103.144). Sin embargo, también me gustaría que los mixins sean parametrizados por la clase de host, para que puedan referirse a sus tipos públicos (usando el modismo de CRTP). El problema surge cuando intento mezclar los dos: la sintaxis correcta no está clara para mí. Por ejemplo, el siguiente código falla al compilar con g ++ 4.4.1:Mixins, plantillas variadic, y 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>()); 

con el error:

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

¿Alguien tiene experiencia exitosa mezcla plantillas variadic con CRTP?

Respuesta

6

Lo siguiente parece funcionar. Agregué Mixins... en las clases mixin heredadas que expande el paquete de parámetros en el lugar. Fuera del cuerpo de la plantilla Host, se deben especificar todos los parámetros de plantilla de Host para que Mixins... sirva para este propósito. Dentro del cuerpo, solo Host es suficiente sin necesidad de deletrear todos sus parámetros de plantilla. Tipo de 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

Lo revisé para incluir el constructor con plantilla. plantilla Host (Args && ... args): Mixins (std :: forward > (args)) ... {} – Sumant

+0

Gracias, Sumant. Tu sugerencia tiene sentido, pero no funciona de alguna manera para mí. ¿Qué versión de compilador estás usando? He copiado y pegado este código y, al compilar, obtuve: tst2.cpp: En la función 'int main()': tst2.cpp: 16: error: no hay función de coincidencia para llamar a 'Host : : Host (Mix1 >, Mix2 >) ' tst2.cpp: 7: nota: los candidatos son: Host :: Host (Mixins > && ...) [con Mixins = Mix1, Mix2] tst2.cpp: 5: nota: Host :: Host (host const &) – Eitan

+0

Oh, me perdí su revisión. Esto corrige el error "no matching function", pero explota con "internal compiler error" :) Entonces, ¿qué compilador estás usando? – Eitan

Cuestiones relacionadas