Stringliteral als Template-Parameter



  • Hoi,
    was ist denn im Moment die gängigste Methode die Limitierung bezüglich von Stringliteralen als Template-Parameter zu umgehen?

    Ich habe ein Funktionstemplate das ich mit bestimmten Parametern einer Scriptsprache zugänglich mache und ich würde gerne zu Debug-Zwecken den exportierten Namen innerhalb der Funktion haben. An der Funktionssignatur kann ich leider nichts ändern.

    So in etwa:

    template<Action A, char const* Name>
    void GenericScriptFunction(ScriptContext* c)
    {
        if(InvalidArguments(c))
            std::cout << Name << " failed because of invalid parameters !";
        foo(c);
    }
    
    ...
    
    ScriptEngine::register("Saufen", &GenericScriptFunction<Action::Saufen, "Saufen">);
    ScriptEngine::register("Rauchen", &GenericScriptFunction<Action::Rauchen, "Rauchen">);
    

    Nur eben in funktionierend. 😉

    Danke und Grüße,
    Ethon


  • Mod

    Ich glaube nicht, dass es dafür eine wirklich gängige Methode gibt. In jdem Fall muss der String irgendwie in einzelne Zeichen aufgebrochen werden. boost arbeitet dabei gerne mit Multibyte-Zeichen.
    Und Sone wird bestimmt gleich ein Makro dafür hervorkramen.



  • Umständlicher Workaround ohne char...-Hacks:

    template <typename T>
    void f(int i)
    {
      std::cout << T::str << ": " << i << '\n';
    }
    
    struct saufen_data { static constexpr char str[] = "Saufen"; };
    constexpr char saufen_data::str[];
    
    int main()
    {
      void (*funktionszeiger)(int) = f<saufen_data>;
      funktionszeiger(0);
    }
    

    Die bevorzugte Lösung wäre wohl auf C++14 zu warten.



  • camper schrieb:

    In jdem Fall muss der String irgendwie in einzelne Zeichen aufgebrochen werden.

    Kann umgangen werden, wenn der String in einem Typ versteckt wird.



  • Danke schon mal. Bin (natürlich erst nach dem Posten...) auf boost::mpl::string gestoßen ... sieht nun etwa so aus:

    template<Action A, int... NameChars>
    void GenericScriptFunction(ScriptContext* c)
    {
        typedef boost::mpl::string<NameChars...> MplName;
        if(InvalidArguments(c))
            std::cout << boost::mpl::c_str<MplName>::value << " failed because of invalid parameters !";
        foo(c);
    }
    
    ...
    
    ScriptEngine::register("Saufen", &GenericScriptFunction<Action::Saufen, 'Sauf', 'en'>);
    ScriptEngine::register("Rauchen", &GenericScriptFunction<Action::Rauchen, 'Rauc', 'hen'>);
    

    Hässlich aber funktionierend...



  • Hab ich kürzlich auch gebraucht, hab den Code grade nicht zur Hand ich glaube die Lösung war wie folgt:

    template<Action A, char const** Name>
    void GenericScriptFunction(ScriptContext* c)
    {
    ...
    }
    
    static const char* SaufenString = "Saufen";
    ScriptEngine::register("Saufen", &GenericScriptFunction<Action::Saufen, &SaufenString>);
    

Log in to reply