Klassen template methode Rückgabewert abhängig von Templatetyp



  • Ich brauche zwei Klassen die sich nur in zwei wesentlichen Dingen unterscheiden: der Typ eines Members und der enum-wert den eine Methode zurückgibt. Ich würde das gerne als Template realisieren um massive Codeduplikation zu vermeiden. Den Member Typ als Template-Parameter festzulegen ist kein Problem, aber wie realisiere ich es, dass die Funktion abhängig vom Membertyp den richtigen enum-Wert zurückliefert, wobei diese Auswertung am besten noch zur Kompilezeit geschehen soll. Hat jemand eine Idee?



  • also existiert eine injektion von den template-typen in die enum-werte?

    dann kannst du doch sowas machen (ungetestet und aus dem stehgreif):

    enum Types // Oder Safe-Enums mit C++11 bzw. Safe-Enum-Idiom in C++03
    {
    	tBool,
    	tInt
    };
    
    template<typename T>
    struct Injection;
    
    template<>
    struct Injection<bool>
    {
    	static const Types Value = tBool;
    };
    
    template<>
    struct Injection<int>
    {
    	static const Types Value = tInt;
    };
    
    // Oder allgemein gegen diesen Boilerplate-Code:
    #define MyLib_MakeInjection(TypeName, EnumName) \
    template<> \
    struct Injection<TypeName> \
    { \
    	static const Types Value = EnumName \
    };
    
    template<typename T, template<class> class MyInjection = Injection>
    struct MyClass
    {
    	T MyData;
    	Types Type() const
    	{
    		return MyInjection<T>::Value;
    	}
    };
    

    edit: falscher kasus.



  • Danke, ich denke so sollte es funktionieren.



  • Ich würde das gerne als Template realisieren

    Du kannst auch private von einer gemeinsamen Basisklasse erben, du kannst die Memberfunktion spezialisieren, du kannst .... auch wild mit defines arbeiten.



  • Funktioniert super mit der injection. Nun habe ich in eine Methode noch die Anforderung, abhängig vom typename T eine Zeichenkette auszugeben. Da habe ich noch keine Idee wie das laufen soll. Meine Versuche eine const char[] in die Injection zu packen, haben leider nicht funktioniert.



  • entweder mit meinem alten ansatz:

    template<typename T>
    struct Injection;
    
    template<>
    struct Injection<bool>
    {
        static char const* const Value;
    };
    template<>
    char const* const Injection<bool>::Value = "bool";
    
    template<>
    struct Injection<int>
    {
        static char const* const Value;
    };
    template<>
    char const* const Injection<int>::Value = "int";
    
    // Komfort:
    #define MyLib_MakeInjection(TypeName) \
    template<> \
    struct Injection<TypeName> \
    { \
        static char const* const Value; \
    }; \
    template<> \
    char const* const Injection<TypeName>::Value = #TypeName;
    
    template<typename T, template<class> class MyInjection = Injection>
    struct MyClass
    {
        T MyData;
        char const* Name() const
        {
            return MyInjection<T>::Value;
        }
    };
    

    oder vererbung:

    template<typename T>
    struct TypeNameCStr;
    
    template<>
    struct TypeNameCStr<bool>
    {
    	char const* Name() const
        {
            return "bool";
        }
    };
    
    template<>
    struct TypeNameCStr<int>
    {
    	char const* Name() const
        {
            return "int";
        }
    };
    
    // Komfort:
    #define MyLib_MakeInjection(TypeName) \
    template<> \
    struct TypeNameCStr<TypeName> \
    { \
    	char const* Name() const \
        { \
            return #TypeName; \
        } \
    };
    
    MyLib_MakeInjection(float)
    MyLib_MakeInjection(char)
    
    template<typename T>
    struct MyClass : public TypeNameCStr<T>
    {
        // ...
    };
    

    ich weiss gar nicht was ihr gegen makros habt, die das ganze wesentlich leserlicher machen.



  • template<> 
    struct Injection<int> 
    { 
        static char const* const Value; 
    }; 
    template<> 
    char const* const Injection<int>::Value = "int";
    

    Gibt ein "template header not allowed in member definition of explicitly specialized class"

    Wenn ich es ändere in

    template<> 
    struct Injection<int> 
    { 
        static char const* const Value; 
    }; 
    char const* const Injection<int>::Value = "int";
    

    Kompiliert es zwar, aber ich bekome ein "multiple definition of Injection<int>::Value"



  • Das

    char const* const Injection<int>::Value = "int";
    

    darf nicht im Header stehen, sonst wird es in jeder Übersetzungseinheit, in der der Header eingebunden wird neu definiert


Log in to reply