Friend und operator bei templaten?



  • Hallo,

    warum kann der Operator nicht auf die i-member zugreifen?

    template<class A>class CTest;
    template<class A,class B> bool operator==(const CTest<A>& a,const CTest<B>& b);
    
    template<class A>class CTest
    {
    	template<class B> friend bool operator==<A,B>(const CTest<A>&,const CTest<B>&);
    	template<class B> friend bool operator==<B,A>(const CTest<B>&,const CTest<A>&);
    
    private:
    	int i;
    };
    
    template<class A,class B> bool operator==(const CTest<A>& a,const CTest<B>& b)
    {
    	return a.i==b.i;
    }
    
    int main()
    {
    	CTest<int> a;
    	CTest<bool> b;
    	a==b;
    }
    


  • Weil Templates nicht zum friend erklärt werden können.

    So geht das richtig:

    template<typename A>
        class CTest
    {
    private:
        int i;
    
    public:
        template <typename B>
            bool operator == (const CTest<B>& rhs)
        { return i == rhs.i; }
    };
    


  • sicher?

    Class templates can have friends. A class or class template, function, or function template can be a friend to a template class. Friends can also be specializations of a class template or function template, but not partial specializations.

    http://msdn2.microsoft.com/en-us/library/f1b2td24.aspx



  • Welchen Compiler benutzt du?



  • VS 2008



  • Mit MSVC 8 (extensions=aus) compiliert dein Code ohne Probleme.
    Comeau spuckt Zähne.

    Keine Ahnung ob das so OK ist.
    Versuch mal die expliziten Parameter wegzugeben (also das "<A,B>" - B kann schön hergeleitet werden), vielleicht gehts dann.
    Wenn nicht würde ich einfach mal sagen dein Compiler kann nicht gut mit template friends umgehen.

    Ansonsten: C++ Standard kaufen und nachgucken 🙂



  • hustbaer schrieb:

    Wenn nicht würde ich einfach mal sagen dein Compiler kann nicht gut mit template friends umgehen.

    Ich saß soeben an dem gleichen Problem unter g++
    template-friends können hierbei offensichtlich nicht auf private-member zugreifen.

    mfg



  • Ich habe den code durch msvc 2005 express laufen lassen und es geht.
    minGW gibt follgende fehlermeldung aus, für die beiden friend declarationen.

    invalid use of template-id operator==<A, B>' in declaration of primary template invalid use of template-idoperator==<B, A>' in declaration of primary template

    Vieleicht bei den einstellungen den schalter
    Spracherweiterungen deaktivieren: auf nein stellen.



  • Wenn der Compiler es für eine "declaration of primary template" hält kann es IMO nicht gehen. Zumindest verstehe ich das so dass er das zuvor deklarierte template im global namespace nicht findet, und daher glaubt dass die friend declaration ein neues template deklariert... Bloss wieso tut er das? *verwirrt-sei*

    camper, wo bist du??? 😃



  • hustbaer schrieb:

    camper, wo bist du??? 😃

    Ich bin ja auch noch da 🙂

    template<class A> class CTest
    {
     template<class X, class Y>
     friend bool operator==( const CTest<X> &a, const CTest<Y>& b );
    
    private:
        int i;
    };
    
    template<class X, class Y>
    bool operator==( const CTest<X> &a, const CTest<Y>& b )
    {
        return a.i == b.i;
    }
    

    👍



  • KasF schrieb:

    hustbaer schrieb:

    camper, wo bist du??? 😃

    Ich bin ja auch noch da 🙂

    template<class A> class CTest
    {
     template<class X, class Y>
     friend bool operator==( const CTest<X> &a, const CTest<Y>& b );
    
    private:
        int i;
    };
    
    template<class X, class Y>
    bool operator==( const CTest<X> &a, const CTest<Y>& b )
    {
        return a.i == b.i;
    }
    

    👍

    Das würde aber bedeuten, dass jegliche operator== friend von CTest sind. Ich möchte aber, dass nur die operator==, mit denen CTest direkt zu tun hat(sagen wir mal operator==<bool,int>(CTest<bool>,CTest<int>), dann soll operator==<bool,int> nur friend von CTest<bool> und CTest<int> sein, und keinen anderen!).

    Ansonsten funktioniert mein Code, wie gepostet, definitiv NICHT.

    template<class A>class CTest;
    template<class A,class B> bool operator==(const CTest<A>& a,const CTest<B>& b);
    
    template<class A>class CTest
    {
    	template<class B> friend bool operator==<>(const CTest<A>&,const CTest<B>&);
    	template<class B> friend bool operator==<>(const CTest<B>&,const CTest<A>&);
    	//template<class A_,class B_> friend bool operator==<>(const CTest<A_>&,const CTest<B_>&);
    
    private:
    	int i;
    };
    
    template<class A,class B> bool operator==(const CTest<A>& a,const CTest<B>& b)
    {
    	return a.i==b.i;
    }
    
    int main()
    {
    	CTest<int> a;
    	CTest<bool> b;
    	a==b;
    }
    
    Error	1	error C2248: 'CTest<A>::i' : cannot access private member declared in class 'CTest<A>'	main.cpp	16
    Error	2	error C2248: 'CTest<A>::i' : cannot access private member declared in class 'CTest<A>'	main.cpp	16
    


  • Ach, bin ich wieder blöd heute. Steht doch da.

    Class templates can have friends. A class or class template, function, or function template can be a friend to a template class. Friends can also be specializations of a class template or function template, but not partial specializations.

    http://msdn2.microsoft.com/en-us/library/f1b2td24.aspx



  • friendlol schrieb:

    Class templates can have friends. A class or class template, function, or function template can be a friend to a template class. Friends can also be specializations of a class template or function template, but not partial specializations.

    http://msdn2.microsoft.com/en-us/library/f1b2td24.aspx

    Das war mir gänzlich unbekannt. Wieder was gelernt 🙂



  • Es gibt n standard workaround, wenn globale operatoren auf internen Daten arbeiten muessen ohne friend zu sein: die Operatoren mittels einer memberfunktion implementieren.
    weiss net ob das mit dem friend so geht

    template<class A> class CTest
    {
     template <class B>
      bool equalTo(CTest<B> const& rhs) const
      { return i==rhs.i;}
     template <class B>
      friend CTest<B>::equalTo() const; 
    private:
        int i;
    };
    
    template<class A, class B>
     bool operator==(CTest<A> const& lhs, CTest<B> const& rhs)
     { return lhs.equalTo(rhs); }
    

    Ganz ohne friends gehts auch:

    template<class A> class CTest
    {
     template <class B>
     bool equalTo(CTest<B> const& rhs) const
      { return rhs.equalTo(i); }
    
     bool equalTo(int i2) const
      { return i2 == i; }
    private:
        int i;
    };
    
    template<class A, class B>
     bool operator==(CTest<A> const& lhs, CTest<B> const& rhs)
     { return lhs.equalTo(rhs); }
    

    Gibt aber natuerlich eine vergleichsmoeglichkeit mit Int's dazu

    Noch eine Moeglichkeit: da alle CTest's ein int beinhalten, erben wir:

    class CTBase {
      int i;
    protected:
      CTBase();
      ~CTBase();
    public:
      bool equalTo(CTBase const& rhs)
       {return rhs.i == i};
    };
    
    template<class A> class CTest : public CTBase
    {
    };
    
    bool operator==(CTBase const& lhs, CTBase const& rhs) //nimmt auch CTest<X>
     { return lhs.equalTo(rhs); }
    

Log in to reply