Explizite Templatespezialisierung



  • Hallo!

    Ich dreh gerade ein wenig am Rad, folgendes compiliert das Visual Studio Express 2005:

    // Code steht in KEINER Templateklasse
    template <typename T> 
    T GetValue() const;
    
    template<>
    int GetValue<int>() const
    			{ 
    				if(GetType() != INT) 
    					throw std::runtime_error("Wrong datatype specified!"); 
    
    				return(*static_cast< const int* >(m_pData)); 
    			}
    

    Soweit, so gut. Nur der MinGW kommt damit gar nicht klar.

    **
    invalid explicit specialization before '>' token
    **

    Ich hab schon viel gegoogelt und weiß grob warum nicht. Es geht wohl darum, dass mindestens ein Templateparameter angegeben werden muss, quasi sowas:

    template<typename T1, typename T2 = void> // bringt aber auch nichts
    

    Allerdings weiß aber auch nicht wie die richtige Syntax lautet.

    Wer lesen will, ich glaube das hier ist's:

    **
    an explicit specialization declaration for a member of a class tem-
    plate or a member template that appears in namespace scope, the member
    template and some of its enclosing class templates may remain unspe-
    cialized, except that the declaration shall not explicitly specialize
    a class member template if its enclosing class templates are not
    explicitly specialized as well. In such explicit specialization dec-
    laration, the keyword template followed by a template-parameter-list
    shall be provided instead of the template<> preceding the explicit
    specialization declaration of the member. The types of the template-
    parameters in the template-parameter-list shall be the same as those
    specified in the primary template definition.**

    Na ja, ich muss gestehen, dass ich da jetzt mehr oder minder blind rumprobiere...
    z.B. soetwas

    template<typename T =int > 
    T GetValue<T>() const
    	            { 
    				if(GetType() != INT) 
    					throw std::runtime_error("Wrong datatype specified!"); 
    
    				return(*static_cast< const T* >(m_pData)); 
    			} 
    // Gibt Fehler: partial specialization `GetValue<T>' of function template
    

    Wäre toll wenn mir da jemand hilft . 🙂 🙂



  • Hallo!

    Probiers mal hiermit:

    // Code steht in KEINER Templateklasse 
     template <typename T> 
     T GetValue() const; 
    
     template<typename T> // Hier muss ein typ in den spitzen Klammern stehen
     T GetValue() const  // im prototyp gibst du ein T und keinen int zurueck
                 { 
                     if(GetType() != INT) 
                         throw std::runtime_error("Wrong datatype specified!"); 
    
                     return(*static_cast< const int* >(m_pData)); 
                 }
    

    mfg LastManStanding



  • MinGW meldet dann das, was leider abzusehen war:

    template<class T> T ClassA::GetValue() const' andtemplate<class T> T ClassA::GetValue() const'

    cannot be overloaded

    😕



  • Funktionstemplates kannst du nicht explizit spezialisieren - aber du kannst sie überladen:

    template<typename T>
    T getVal();
    
    int getVal()
    {...}
    

    (btw, wozu brauchst du das überhaupt?)



  • CStoll schrieb:

    Funktionstemplates kannst du nicht explizit spezialisieren - aber du kannst sie überladen:

    template<typename T>
    T getVal();
    
    int getVal()
    {...}
    

    (btw, wozu brauchst du das überhaupt?)

    Siehe hier:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-141577.html

    Ich hatte mich entschlossen die Methode aus dem letzten Post zu verwenden, allerdings hab ich erst jetzt festgestellt, dass der MinGW damit nicht einverstanden ist... aber das ist halt die eleganteste Möglichkeit und ich würde sie gerne beibehalten.

    Soweit ich weiß dürfen sich Methoden bei der Überladung nicht ausschließlich durch den Rückgabetyp unterscheiden, ich teste es mal eben...

    es geht
    😮 😮 😮 unglaublich, das mag ich ja gar nicht glauben. Damit spiel ich erstmal rum 😉



  • Ich wusste, da war etwas. Wenn man das Spielchen so weitertreibt und jetzt für die anderen Datentypen überlädt, gibt es folgende Meldung:

    **
    unsigned int ClassA::GetValue() const' andint ClassA::GetValue() const'
    cannot be overloaded
    **

    Wäre super, wenn einer der Forum-Gurus mir da helfen könnte (und sei es nur durch die Aussage "Mit dieser Template-Variante geht das beim MinGW schlichtweg nicht").
    Ich glaube, alleine komme ich da nicht mehr weiter 👎



  • CStoll schrieb:

    Funktionstemplates kannst du nicht explizit spezialisieren

    Das ist falsch. Funktionstemplates kann man nicht partiell spezialisieren (stattdessen kann man sie überladen). Explizite spezialisieren kann man sie hingegen schon.

    Das:

    // 1. Base Template
    template <class T>
    T getValue();
    
    // 2.
    template <>
    int getValue<int>() {
    return 0;
    }
    

    ist legales C++ und 2. eine explizite Spezialisierung des Base Templates.

    Das hier:

    template <typename T>
    T GetValue() const;
    

    muss ja *innerhalb* einer Klassendefinition stehen. Andernfalls wäre die const-Deklaration ein Fehler.

    Steht nun das hier:

    template<>
    int GetValue<int>() const
                {
                    if(GetType() != INT)
                        throw std::runtime_error("Wrong datatype specified!");
    
                    return(*static_cast< const int* >(m_pData));
                }
    

    ebenfalls *innerhalb* der Klassendefinition, wäre der Fehler klar: Eine explizitze Spezialisierung ist nur innerhalb eines Namespace-Scopes zulässig. Nicht aber innerhalb eines Klassenscopes.
    Die korrekte Lösung:

    class Foo {
    public:
        template <typename T>
        T GetValue() const;
    };
    
    // Definition des Base-Templates
    template <class T>
    T Foo::GetValue() const {
        // ...
        return T();
    }
    
    // Definition einer expliziten Spezialisierung
    template <>
    int Foo::GetValue<int>() const {
        // ...
        return 42;
    }
    

    So sähe das für ein Member-Template aus.

    Vielleicht ist Foo aber auch ein Template und GetValue nur eine normale Methode?

    template <class X>
    class Foo {
    public:
    
        X GetValue() const;
    };
    
    // Definition des Base-Templates
    template <class X>
    X Foo<X>::GetValue() const {
        // ...
        return X();
    }
    
    // Definition einer expliziten Spezialisierung
    template <>
    int Foo<int>::GetValue() const {
        // ...
        return 42;
    }
    

    Sollte hingegen Foo ein Template sein und GetValue ein Member-Template, dann ist ist eine explizite Spezialisierung von GetValue nur bei gleichzeitiger Spezialisierung von Foo möglich:

    template <class X>
    class Foo {
    public:
        template <class T>
        T GetValue() const;
    };
    
    // Definition des Base-Templates
    template <class X>
    template <class T>
    T Foo<X>::GetValue() const {
        // ...
        return X();
    }
    
    // Definition einer expliziten Spezialisierung
    template <>
    template <>
    int Foo<int>::GetValue<int>() const {
        // ...
        return 42;
    }
    

    All das ändert nichts an der Tatsache, dass eine Überladung meist sinnvoller als einer Spezialisierung ist.



  • Da wäre ich niemals drauf gekommen.
    Ich glaube, an dieser Stelle ist es mal an der Zeit, zurückzublicken und einfach nur "Danke" zu sagen 😉 🤡

    Einige Leute in diesem Forum haben ein Wissen über C++, das ist unglaublich 👍



  • @explizit:
    Mal ne andere Frage.
    Wie sieht denn der Code aus der irgendwann mal links von GetValue stehen soll?
    Da musst du doch auch schon im Vorfeld wissen welchen Typ dir GetValue zurückliefert.

    MfG Spacelord


Log in to reply