Spazialisierung von Forward Template Function als friend, WIE?!



  • Hallo,

    template<typename Ty>
        class property;
    
        template<typename Ty>
        std::ostream& operator<<(std::ostream& os, const property<Ty>& value);
    
        template<typename Ty>
        class property: public property_base
        {
        public:
            friend std::ostream& operator<<(std::ostream& os, const property<Ty>& value); // <- zeile 56
        };
    

    Funktioniert auf allen möglichen GCCs unter 4.0 mit folgender Warnung (Gibt Linkerfehler, aber das ist ja klar angesichts der Meldung):

    proctools/property.h:56: warning: friend declaration `std::ostream&
       proctools::operator<<(std::ostream&, const proctools::property<Ty>&)'
       declares a non-template function
    proctools/property.h:56: warning: (if this is not what you intended, make sure
       the function template has already been declared and add <> after the
       function name here) -Wno-non-template-friend disables this warning
    

    Tu ich wie mir geheissen, schreibe also operator<< <>, compiliert's wunderbar und funktioniert auch, um genau zu sein seit zwei Wochen, aber nun gebe ich das raus, und als allererstes GEHT'S NICHT MEHR mit gcc 4.0 😡

    Kann mir nun einer sagen wie's heissen muss damit es auf ALLEN verfluchten GCCs läuft?!

    EDIT:
    PS: Versucht habe ich natürlich schon alles mögliche, ich poste hier erst wenn ich schon kurz vorm Nervenzusammenbruch stehe 😉

    EDIT:
    Die GCC4 Fehlermeldung lautet:

    proctools/property.h:56: error: declaration of 'operator<<' as non-function
    proctools/property.h:56: error: expected ';' before '<' token
    


  • Um mal ein Selbstgespräch zu führen, ich glaube ich habe mich bei der Lösung durch Folgefehler die nun widerum vom gcc 2.95.4 ausgespuckt werden irritieren lassen...

    friend std::ostream& operator<< <Ty>(std::ostream& os, const property<Ty>& value);
    

    🙄

    EDIT:
    Nein, laut VC8 (der einzige neuere Compiler neben dem gcc 3.2 den ich hier habe) ist das auch falsch:

    property.cpp(34) : error C2143: syntax error : missing ';' before '<'
    property.cpp(38) : see reference to class template instantiation 'property<Ty>' being compiled
    property.cpp(34) : error C2433: '<<' : 'friend' not permitted on data declarations
    property.cpp(34) : error C2365: 'operator <<' : redefinition; previous definition was 'function'
    property.cpp(9) : see declaration of 'operator <<'
    property.cpp(34) : error C2530: '<<' : references must be initialized
    property.cpp(34) : error C2238: unexpected token(s) preceding ';'
    


  • Ich mag mich zwar irren, aber mitunter MUSST du dem Compiler wirklich dazusagen, daß er es mit Templates zu tun hat:

    friend template<> ostream& operator<<(...);
    

    Oder du definierst den op<< erst, nachdem du die Klassendeklaration durch hast:

    template<typename Ty>
    class property
    {
      friend ostream& operator<<(ostream&,const property<Ty>&);//notfalls ohne das <Ty> probieren
      ...
    };
    
    template<typename Ty>
    ostream& operator<<(ostream& sout,const property<Ty>& data)
    {
      ...
    }
    


  • Danke für den Hinweis, tatsächlich funktioniert es mit dem VC8 und dem gcc 4.0 (das war eines von "versucht habe ich schon alles mögliche") folgendermassen (was mir auch eingängig scheint, denn es wird eine Template-Deklaration mit einem Parameter erwartet, und der Templateparameter wird durch das umgebende Klassentemplate besetzt).

    template<typename Ty>
        class property;
    
        template<typename Ty>
        std::ostream& operator<<(std::ostream& os, const property<Ty>& value);
    
        template<typename Ty>
        class property: public property_base
        {
        public:
    	template<typename>
            friend std::ostream& operator<<(std::ostream& os, const property& value);
    
        private:
            Ty m_value;
        };
    

    Allerdings besteht der gcc 3.2 auf folgender Lösung (die aber mit zumindest dem VC8, hoffentlich auch mit dem gcc 4.0 funktioniert):

    template<typename Dummy>
            friend std::ostream& operator<<(std::ostream& os, const property<Dummy>& value);
    


  • Letztere Lösung sollte auch die Richtige sein. Du wiederholst im friend ja die Deklaration vom operator<< - und die muss auch wieder ein Template sein. Dass die umschließende Klasse auch ein Template ist, spielt dabei erstmal keine Rolle - denn der friend gehört nicht zur Klasse (der friend schon, aber nicht die bezeichnete Funktion) und hängt auch nicht von deren Templateparametern ab. Demnach sollte dort auch die Template Name Injection nicht funktionieren (weshalb du nicht einfach property schreiben kannst, sondern property<Dummy> schreiben musst).


Anmelden zum Antworten