Methodenüberladung in Template-Klassen



  • drakon schrieb:

    hustbaer schrieb:

    Comeau frisst es gar nicht.

    Mich verwirrt am meisten, dass VC das schluckt, auch wenn man die Spracherweiterungen abschaltet. Ohne die sollte er sich doch exakt an den Standard halten.. :S

    DAS verwirrt mich nicht, MSVC hat einfach noch ein paar Bugs was Templates angeht 🙂

    ----

    Aber ganz egal wie das jetzt mit den offiziellen Regeln ist, ich würde es auf jeden Fall nicht mit Spezialisierung machen, sondern mit der "nodes_impl" Variante.

    Hmm. Ich sehe ehrlich gesagt den Grund nicht ganz, warum man das über überhaupt über templates steuern soll.. Lediglich dass man keinen Namen nehmen muss finde ich das ein wenig übertrieben.

    Äh. Die "nodes_impl" Variante von mir verwendet ja auch keine Templates.
    😕



  • Bugs und es funktioniert? 😛

    Das wegen den templates war eigentlich auf den Ursprungs post bezogen.



  • drakon schrieb:

    Bugs und es funktioniert? 😛

    Na klar.
    Bei VC6 konnte (bzw. musste) man typename weglassen und es hat funktioniert 🙂



  • drakon schrieb:

    template<class N, class ON>
    class A
    {
    public:
    
    	template<class T>
    	void nodes();
    
    	template<>
    	void nodes<N>()
    	{
    		std::cout << "N\n";
    	}
    
    	template<>
    	void nodes<ON>()
    	{
    		std::cout << "ON\n";
    	}
    
    private:
    };
    
    int main()
    {
    	A<int,float> a;
    	a.nodes<int>(); // N
    	a.nodes<float>(); // ON
    }
    

    Das gefällt mir so sehr gut. Nur will g++ das nicht kompilieren (habe -std=c++0x als Kompileroption gesetzt). Kann das g++ (bisher) überhaupt nicht? Falls dem so ist: Gibt es einen anderen Open-Source-Kompiler, der das kann?

    drakon schrieb:

    Hmm. Ich sehe ehrlich gesagt den Grund nicht ganz, warum man das über überhaupt über templates steuern soll.. Lediglich dass man keinen Namen nehmen muss finde ich das ein wenig übertrieben.

    Ich vermute, dass kann man so auch nicht sehen (ohne weitere Teile des Programms zu kennen). Bei mir ist nur der Eindruck entstanden, dass so wie es bisher ist, die Lesbarkeit meines Codes spürbar leidet.

    hustbaer schrieb:

    Letzte Möglichkeit die ich anzubieten habe, und IMO die beste:

    template<class N> class A
    {
    public:
        vector<N*> nodes() const
        {
            return nodes_impl();
        }
    
    private:
        virtual vector<N*> nodes_impl() const = 0;
    };
    
    template<class N, class ON> class B : public virtual A<N>
    {
    public:
        vector<ON*> nodes() const // neue nodes() funktion, verdeckt A::nodes()
        {
            // ...
        }
    
    private:
        virtual vector<N*> nodes_impl() const // override von A::nodes_impl, implementiert A::nodes()
        {
            // ...
        }
    };
    

    Ich habe wohl noch eine Nebenbedingung vergessen: Wenn ich ein Objekt b der Klasse B habe, würde ich gerne beide nodes()-Funktionen auf b anwenden können. Das geht bei der Lösung doch nur, indem ich b zu A caste?



  • ingobulla schrieb:

    Nur will g++ das nicht kompilieren (habe -std=c++0x als Kompileroption gesetzt). Kann das g++ (bisher) überhaupt nicht? Falls dem so ist: Gibt es einen anderen Open-Source-Kompiler, der das kann?

    Wie wärs wenn du uns die Infos lieferst, warum g++ das nicht compilieren will? Dann kann man dir vielleicht sogar helfen, g++ dazu zu bringen es doch zu compilieren...



  • pumuckl schrieb:

    Wie wärs wenn du uns die Infos lieferst, warum g++ das nicht compilieren will? Dann kann man dir vielleicht sogar helfen, g++ dazu zu bringen es doch zu compilieren...

    Danke für den freundlichen Hinweis:

    ../src/scratch.h:9: error: explicit specialization in non-namespace scope ‘
        class A<N, ON>’
    ../src/scratch.h:10: error: template-id ‘nodes<N>’ in declaration of
        primary template
    ../src/scratch.h:15: error: explicit specialization in non-namespace scope ‘
        class A<N, ON>’
    ../src/scratch.h:16: error: template-id ‘nodes<ON>’ in declaration of
        primary template
    ../src/scratch.h:16: error: ‘void A<N, ON>::nodes()’ cannot be overloaded
    ../src/scratch.h:10: error: with ‘void A<N, ON>::nodes()’
    


  • ingobulla schrieb:

    ../src/scratch.h:9: error: explicit specialization in non-namespace scope
    

    Heißt übersetzt: "Du hast eine Templatespezialisierung (nämlich die von nodes<N>, Anm.d.Übers.) in einem Gültigkeitsbereich (Scope) definiert, der kein Namespace ist! (Nämlich im Scope von class A<N, ON>)"

    Andersrum ausgedrückt heißt das, du musst die Spezialsierung außerhalb der Klasse definieren.
    Das ist allerdings auch nicht möglich, da void A<N, ON>::node<T>() als Ganzes ein Funktionstemplate ist, das nicht partiell spezialsiert werden darf - sprich, Spezialisierungen sind nur über N, ON und T möglich, nicht aber nur über T.
    Um das Problem zu lösen, könntest du die Spezialisierung auf ein Functor-Template umleiten, die dann möglich wäre.



  • drakon schrieb:

    Mich verwirrt am meisten, dass VC das schluckt, auch wenn man die Spracherweiterungen abschaltet. Ohne die sollte er sich doch exakt an den Standard halten.. :S

    Gibt es in MSVC++ wirklich so viele Erweiterungen auf Sprachebene (nicht CLI)? Mir fallen da z.B. Referenzen auf temporäre RValues ein, aber da gibts auch immer schön Warnungen.



  • ingobulla schrieb:

    Ich habe wohl noch eine Nebenbedingung vergessen: Wenn ich ein Objekt b der Klasse B habe, würde ich gerne beide nodes()-Funktionen auf b anwenden können. Das geht bei der Lösung doch nur, indem ich b zu A caste?

    Nö, du kannst direkt ptr->A::nodes() schreiben.



  • Nexus schrieb:

    drakon schrieb:

    Mich verwirrt am meisten, dass VC das schluckt, auch wenn man die Spracherweiterungen abschaltet. Ohne die sollte er sich doch exakt an den Standard halten.. :S

    Gibt es in MSVC++ wirklich so viele Erweiterungen auf Sprachebene (nicht CLI)? Mir fallen da z.B. Referenzen auf temporäre RValues ein, aber da gibts auch immer schön Warnungen.

    Naja da gibt's schon ein paar:

    http://msdn.microsoft.com/en-us/library/34h23df8(v=VS.80).aspx



  • Danke für den Link. Mal schauen, ob ich nicht aus Versehen ein paar davon benutze... 🙂



  • Nexus schrieb:

    drakon schrieb:

    Mich verwirrt am meisten, dass VC das schluckt, auch wenn man die Spracherweiterungen abschaltet. Ohne die sollte er sich doch exakt an den Standard halten.. :S

    Gibt es in MSVC++ wirklich so viele Erweiterungen auf Sprachebene (nicht CLI)? Mir fallen da z.B. Referenzen auf temporäre RValues ein, aber da gibts auch immer schön Warnungen.

    Ich weiss nicht in wie fern das dokumentiertes Verhalten ist, dass Sachen gehen, die nicht im Standard vorgesehen sind, aber ich bezweifle stark, dass das irgendwelche Bugs sind. Daher sind das imo Spracherweiterungen, da ja offensichtlich mehr akzeptiert wird.
    Ich war bis jetzt der Auffassung, dass VC beim Ausschalten der Spracherweiterungen sich wirklich so exakt an den Standard hält, wie möglich, auch wenn das bedeutet, dass gewisse Konstrukte (obwohl möglich) nicht gehen.



  • drakon, glaub mir, das sind z.T. Bugs:

    http://msdn.microsoft.com/en-us/library/x84h5b78.aspx

    Der "dependent names" Bug kann z.B. dazu führen dass Code geht, der nicht gehen sollte.
    Der Grossteil sind allerdings wirklich Bugs, wo höchstens Dinge nicht gehen, die eigentlich gehen sollten.



  • hustbaer schrieb:

    Oder du kannst etwas wie boost::type<> und ganz normale Overloads verwenden:

    class foo
    {
    public:
        void bar(boost::type<baz>);
        void bar(boost::type<qux>);
    };
    
    void test()
    {
        foo f;
        f.bar(boost::type<baz>());
        f.bar(boost::type<qux>());
    }
    

    Kann mir jemand sagen, in welcher Boost-Library ich boost::type<> finde?



  • Keine Ahnung zu welcher "Library" das zählt. mMn müsste es zur "Utility" zählen, aber in der Doku isses nicht gelistet.

    Inkludiere einfach <boost/type.hpp> und du bist dabei 🙂


Anmelden zum Antworten