2010-03-17 15 views
11

Hier ist das Szenario: Ich hätte gerne eine Host-Klasse, die eine variable Anzahl von Mixins haben kann (nicht zu hart mit variadischen Vorlagen - siehe zum Beispiel http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.103.144). Ich möchte aber auch, dass die Mixins von der Host-Klasse parametrisiert werden, so dass sie sich auf ihre öffentlichen Typen beziehen können (unter Verwendung des CRTP-Idioms). Das Problem tritt auf, wenn versucht wird, die beiden zu mischen - die richtige Syntax ist mir unklar. Zum Beispiel der folgende Code nicht mit g ++ 4.4.1 kompilieren:Mixins, variadic Vorlagen und 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>()); 

Mit dem Fehler:

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

Hat jemand erfolgreiche Erfahrung Mischen variadische Vorlagen mit CRTP?

Antwort

6

Folgendes scheint zu funktionieren. Ich habe Mixins... in den geerbten Mixin-Klassen hinzugefügt, wodurch das Parameterpack inplace erweitert wird. Außerhalb des Körpers der Host Vorlage müssen alle Vorlagenparameter von Host spezifiziert werden, also Mixins... dient dem Zweck. Innerhalb des Körpers, nur Host ist ausreichend, keine Notwendigkeit, alle seine Template-Parameter zu buchstabieren. Eine Art kurze Hand.

#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

Ich überarbeitete es, um templates Konstruktor zu enthalten. Vorlage Host (Args && ... args): Mixins (Std :: weiter > (args)) ... {} – Sumant

+0

Danke, Sumant. Ihr Vorschlag macht Sinn, funktioniert aber irgendwie nicht für mich. Welche Compiler-Version verwenden Sie? Ich habe diesen Code kopiert und eingefügt und beim Kompilieren: tst2.cpp: In der Funktion 'int main()': tst2.cpp: 16: Fehler: Keine passende Funktion für den Aufruf von 'Host : : Host (Mix1 >, Mix2 >) ' tst2.cpp: 7: Hinweis: Kandidaten sind: Host :: Host (Mixins > && ...) [mit Mixins = Mix1, Mix2] tst2.cpp: 5: Hinweis: Host :: Host (const Host &) – Eitan

+0

Oh, ich habe Ihre Revision verpasst. Dies behebt den "no matching function" -Fehler, explodiert aber mit "internem Compilerfehler" :) Also, welchen Compiler benutzen Sie noch? – Eitan