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).


Log in to reply