Template-Spezialisierung: const char* const& --> Linker-Fehler



  • Ich will eigentlich nur einen ganz normalen konstanten oder nicht konstanten C-String übergeben.
    Das Problem ist, dass die vorgegebene Template-Funktion schon fest legt, dass es eine const Ref ist. -> Logisch wär const char*const&. Und eine const Referenz auf einen Zeiger müsste doch im Endeffekt dasselbe sein wie der Zeiger.



  • Ich will eigentlich nur einen ganz normalen konstanten oder nicht konstanten C-String übergeben.
    Das Problem ist, dass die vorgegebene Template-Funktion schon fest legt, dass es eine const Ref ist. -> Logisch wär const char*const&. Und eine const Referenz auf einen Zeiger müsste doch im Endeffekt dasselbe sein wie der Zeiger.

    Versuchs jetzt mit ner normalen Überladung

    void foo(const char *) { 
      //..irgendwas machen 
    }
    
    //oder
    template<> 
    void foo(const char * const&) { 
      //..irgendwas machen 
    }
    

    Geht beides. Im Beispiel ... Mal schauen, was ich mir damit für neue Probs einhandle.



  • Funktionen müssen so gut wie nie spezialisiert wrden.



  • Außer, wenn man z.B. den Rückgabewert festlegen will (ich hab in wirlichkeit mehrere Template-Parameter). Aber ich kann auch ne Ausnahme machen und für const char* überladen.

    Prinzipiell tät mich aber schon interessieren, warum das nicht geht. Standard-Conform wärs ja wohl, oder?

    Voila:

    7,8 h für die Portierung eines nicht so kleinen Konsolen-Projekts von Borland C++-Builder 5.5 nach VC 7.1. Zumindest compiliert und linkt es jetzt. 0 Fehler, 0 Warnungen. Hoffe keine Laufzeitfehler eingebaut zu haben. *puh* (ich mach das bestimmt nicht freiwillig)



  • Warum - du hast doch gesagt, dass überladen reicht.



  • Ja es geht, ist aber nicht analog zu anderen Teilen der Bibliothek und deswegen nicht so schön. Außerdem wird die Bibliothek in mehreren Projekten eingesetzt und und ich muss jetzt wegen des Verhaltens von VC und einer einzigen Applikation die Bibliothek ändern, ne neue Version rausbringen etc.. Und ich möcht wissen, warum es nicht geht, abgesehen davon, dass ichs umgehen kann.



  • (Sorry, dass fällt mir erst jetzt ein)
    Dann geh über strukturen:

    namespace help
    {
        template<class T,class U>
        struct specialise_h
        {
            typedef void ret;
            static ret foo(T t,U u)
            {
                //...
            };
        };
    
        template<class T,class U>
        struct specialise_h<const T&, U>
        {
            typedef bool ret;
            ret foo(const T& t,U u)
            {
                //...
                return x;
            };
        };
    };
    
    template<class T,class U>
    typename help::specialie_h<T,U>::ret foo(T t,U u)
    {
        return help::specialise_h::foo(t,u);
    };
    


  • Prinzipiell tät mich aber schon interessieren, warum das nicht geht. Standard-Conform wärs ja wohl, oder?

    Das geht nicht, da bei Referenzparametern in Templates kein "decaying" stattfindet.
    Was soviel bedeutet wie, dass ein Array in diesem Fall nicht in "Zeiger auf das erste Element" zerfällt. Dies wäre aber nötig, da ein Stringliteral den Typ const char[] hat und nicht const char*.

    Für ein Stringliteral wird hier also das Base-Template und nicht die Spezialisierung ausgewählt. Weist du hingegen das Stringliteral zuvor einer Variablen vom Typ const char* zu, dann wird auch die Spezialisierung aufgerufen.



  • Heißt das, er müsste noch für const char[] spezialisieren?



  • ness schrieb:

    Heißt das, er müsste noch für const char[] spezialisieren?

    Der Typ von T ist hier const char[N], wobei N die Länge des Stringliterals ist. Für diesen Typen kannst du die Funktion so aber nicht spezialisieren, da du N nicht zur Verfügung hast.

    Also: solange das Base-Template einen Referenzparameter enthält ist eine Spezialisierung für Stringliterale nicht möglich, da es für Funktionen keine partielle Spezialisierung gibt.

    Man könnte die Funktion allerdings entsprechend überladen:

    template <int N>
    void foo(const char (&a)[N]);
    

    Wobei eine Überladung für const char* hier sicher angebrachter wäre.



  • Wenn er sicher gehen möchte soll er doch ne ganz normale Funktion draus machen.
    Bei der Auflösung von Überladungen spielen doch die spezialisierten Versionen erst dann eine Rolle wenn das "passenste" base template gefunden wurde.Wenn es von diesem base Template eine passende Spezialisierung gibt wird diese genommen und ansonsten eine generiert.
    Die ganze Spezialisierung von Funktionstemplates verhält sich etwas "unnatürlich".

    MfG Spacelord



  • Überladen hab ich inzwischen. Und verstanden warum ichs machen muss auch. Danke! 👍


Anmelden zum Antworten