Templatespezialisierung und statische Membervariable



  • Ich verwendete folgendes im GCC um Namen mit Typen sozusagen zu verbinden:

    template <typename T>
    struct name_of {
        constexpr static const char* value = "undefined";
    };
    
    #define NAMEOFDECL(type, name)                      \
    template <>                                         \
    struct name_of <type> {                             \
        constexpr static const char* value = name;      \
    }
    
    NAMEOFDECL(void,                "void");
    NAMEOFDECL(char,                "char");
    NAMEOFDECL(unsigned char,       "unsigned char");
    

    Als ich das ganze dann mit dem MSVC compiler versucht habe zu bauen bin ich auf das Problem gestoßen, dass constexpr und die in class initialisation nicht unterstützt wird.

    Also habe ich folgendes versucht:

    #ifndef _MSC_VER
    #define CONSTEXPR constexpr
    #else
    #define CONSTEXPR
    #endif
    
    template <typename T>
    struct name_of {
        CONSTEXPR static const char* const value;
    };
    template <typename T> CONSTEXPR const char* const name_of<T>::value = "undefined";
    
    #define NAMEOFDECL(type, name)											\
    template <>																\
    struct name_of <type> {													\
        CONSTEXPR static const char* const value;							\
    };																		\
    CONSTEXPR const char* const name_of<type>::value = name;
    
    NAMEOFDECL(void,                "void");
    NAMEOFDECL(char,                "char");
    // ...
    

    Das kompiliert zwar, linkt aber nicht. Vermutlich eine ODR Verletzung.
    Die Initialisierungen der statischen Variablen kann ich auch nicht in die Source Datei verschieben, weil sie von einem Templateparameter abhängen

    Wie löse ich das Problem jetzt, damit ich später folgendes Problemlos bauen kann:

    std::cout << name_of <int>::value << "\n";
    


  • Funktionen statt Konstanten.

    Nimm auuserdem # im Präprozessor, spart Codeduplikation.

    z0r 😮



  • Versuchs mal mit static constexpr char * const.
    BTW, den # operator des Präprozessors kennste schon, oder?


  • Mod

    Als ich das ganze dann mit dem MSVC compiler versucht habe zu bauen bin ich auf das Problem gestoßen, dass constexpr und die in class initialisation nicht unterstützt wird.

    Du musst natürlich den Typ abändern:

    static constexpr char value[] = "undefined";
    // [...]
    static constexpr char value[] = name;
    

  • Mod

    Ich verwendete folgendes im GCC um Namen mit Typen sozusagen zu verbinden:

    Wie wär's mit typeid(...).name() und abi::__cxa_demangle ?



  • Randinfo: Verwende vc120 toolset (VC 2013).

    z0r schrieb:

    Funktionen statt Konstanten.
    Nimm auuserdem # im Präprozessor, spart Codeduplikation.

    Nathan schrieb:

    Versuchs mal mit static constexpr char * const.
    BTW, den # operator des Präprozessors kennste schon, oder?

    Bisher nicht ^^. Ist an mir vorbeigegangen.

    Arcoth schrieb:

    Ich verwendete folgendes im GCC um Namen mit Typen sozusagen zu verbinden:

    Wie wär's mit typeid(...).name() und abi::__cxa_demangle?

    Darauf will ich micht nicht verlassen / bzw ich habe ja jetzt zum Beispiel den Compiler gewechselt, vielleicht kommt das wieder vor.

    Bei allem ohne constexpr:

    1> error C2864: 'name_of<long>::value' : a static data member with an in-class initializer must have non-volatile const integral type
    1> type is 'char []'

    mit constexpr (Sinngemäß): "; expected before char".
    Für mich ist das ein klares: Ich kenne constexpr nicht.

    Ich versuche es jetzt mal mit statischen Funktionen (bzw Methoden).
    EDIT: Ja, das funktioniert besser 😉 mache ich es eben so.


Log in to reply