Template-Spezialisierung durch integralen Typ



  • Hallo,

    ich habe einen Template-Parameter integralen Typs. Wenn dieser einen speziellen Wert (0) hat, dann benötige ich einen zusätzlichen Konstruktor-Parameter.
    Funktioniert auch wunderbar:

    template<size_t n>
    struct TypeTrait {
    	enum { num = n };
    	typedef void CONSTRUCTOR_PARAM0;
    };
    
    template<>
    struct TypeTrait<0> {
    	size_t num;
    	typedef size_t CONSTRUCTOR_PARAM0;
    };
    
    template<size_t n>
    struct st : public TypeTrait<n>
    {
    	st(CONSTRUCTOR_PARAM0);
    };
    
    template<size_t n>
    st<n>::st(CONSTRUCTOR_PARAM0) {}
    
    template<>
    st<0>::st(CONSTRUCTOR_PARAM0 n) {num = n;}
    

    Wenn ich aber weitere Template-Parameter habe, sieht das ganze nicht mehr so rosig aus:

    template<size_t n>
    struct TypeTrait {
    	enum { num = n };
    	typedef void CONSTRUCTOR_PARAM0;
    };
    
    template<>
    struct TypeTrait<0> {
    	size_t num;
    	typedef size_t CONSTRUCTOR_PARAM0;
    };
    
    template<size_t n, bool b, int i>
    struct st : public TypeTrait<n>
    {
    	st(CONSTRUCTOR_PARAM0);
    };
    
    template<size_t n, bool b, int i>
    st<n, b, i>::st(CONSTRUCTOR_PARAM0) {}
    
    template<bool b, int i>
    st<0, b, i>::st(CONSTRUCTOR_PARAM0 n) {num = n;}
    
    Line 29	error C2182	'n': illegal use of type 'void'
    Line 29	error C2244	'st<n, b, i>::st': unable to macht function definition to an existing declaration
    

    Wie kann ich dennoch mein Ziel erreichen?

    PS: Da die restlichen Member meiner echten Klasse von diesem TypeTrait NICHT betroffen sind, würde ich die sehr ungern die Klasse selbst spezialisieren.

    Danke vorab.



  • Mit einem ordentlichen Compiler sollte schon das erste nicht compiliert werden.
    So müsste es eigentlich aussehen:

    template<std::size_t n>
    struct TypeTrait 
    {
        enum { num = n };
        typedef void CONSTRUCTOR_PARAM0;
    };
    
    template<>
    struct TypeTrait<0> 
    {
        std::size_t num;
        typedef std::size_t CONSTRUCTOR_PARAM0;
    };
    
    template<std::size_t n>
    struct st;
    
    template<std::size_t n>
    struct st : public TypeTrait<n>
    {
        st(typename TypeTrait<n>::CONSTRUCTOR_PARAM0);
    };
    
    template<std::size_t n>
    st<n>::st(typename TypeTrait<n>::CONSTRUCTOR_PARAM0) {}
    
    template<>
    struct st<0> : public TypeTrait<0>
    {
        st(TypeTrait<0>::CONSTRUCTOR_PARAM0 n){num = n;};
    };
    
    int main()
    {
    }
    


  • Warum sollte das erste nicht kompilieren?
    Du brauchst nicht umständlich über typename TypeTrait::type gehen, da das typedef public ist und von TypeTrait ja geerbt wird.

    Falls du das nicht auf das typedef bezogen hast: Welches Problem sahst du noch?

    EDIT:
    Du hast auch überlesen, dass ich geschrieben habe, dass ich die class/struct selbst nicht überladen will, da ansonsten alle Member nicht vom TypeTrait abhängig sind und ich sonst jede Menge Redundanz hätte.



  • Warum überhaupt die Vererbung in Tachyons Variante?



  • Ad aCTa schrieb:

    Warum überhaupt die Vererbung in Tachyons Variante?

    Weil "num" sonst inexistent in st wäre.



  • FrEEzE2046 schrieb:

    Warum sollte das erste nicht kompilieren?
    Du brauchst nicht umständlich über typename TypeTrait::type gehen, da das typedef public ist und von TypeTrait ja geerbt wird.

    Doch musst Du. Der einzige mit bekannte Compiler, des den Code so schlueckt, ist MSVC. Ich kann Dir die Regel die das eigentlich verbietet nicht nennen, da ich die Seite nicht kenne.

    FrEEzE2046 schrieb:

    Falls du das nicht auf das typedef bezogen hast: Welches Problem sahst du noch?

    Du versuchst, einen Ctor für eine spezialisierte Klasse zu definieren. Es gibt aber keine Definition für die spezialisierte Klasse. Das kann nicht funktionieren...



  • Tachyon schrieb:

    Das kann nicht funktionieren...

    Es funktionert ja. Nur eben nicht, bei mehreren Template-Parametern.



  • FrEEzE2046 schrieb:

    Tachyon schrieb:

    Das kann nicht funktionieren...

    Es funktionert ja. Nur eben nicht, bei mehreren Template-Parametern.

    Tachyon schrieb:

    [...]Der einzige mit bekannte Compiler, des den Code so schlueckt, ist MSVC[...]

    Das liegt nur daran, dass VC++ ziemlich schlaffe Regeln hat...
    VC++ schluckt auch solche tollen Dinge wie das hier:

    template<typename T>
    struct S
    {
        typedef T T; //??
    };
    

    Das Gleiche gilt für viele andere fehlerhafte Konstrukte mit Templates.



  • Also bleibt mir nichts anderes übrig, als wegen dem einen type trait die ganze Klasse zu spezialisieren?



  • FrEEzE2046 schrieb:

    Also bleibt mir nichts anderes übrig, als wegen dem einen type trait die ganze Klasse zu spezialisieren?

    Wie wäre es denn mit einem Template-Ctor?


Log in to reply