Search code examples
c++templatesoperator-overloadingfunction-definitionfriend-function

Overloading << and >> as outside member functions for template class


I am trying to define my operator overloading outside the class like this:

template <typename Type>
class myClass
{
    ...
    friend std::ostream& operator << (std::ostream&, const myClass&);
    friend std::istream& operator >> (std::istream&, myClass&);
    ...
}

template <typename Type>
std::ostream& myClass<Type> :: operator << (std::ostream& out, const myClass<Type>& other) { ... }

template <typename Type>
std::istream& myClass<Type> :: operator >> (std::istream& in, myClass<Type>& other) { ... }

My problem is that I get an error saying something like "class template class has no member operator<<" and I do not understand how or why is this happening.


Solution

  • For starters the friend functions are not member functions of the class where they are declared.

    So these declarations in any case are incorrect.

    template <typename Type>
    std::ostream& myClass<Type> :: operator << (std::ostream& out, const myClass<Type>& other) { ... }
    
    template <typename Type>
    std::istream& myClass<Type> :: operator >> (std::istream& in, myClass<Type>& other) { ... } 
    

    Secondly within the class definition you declared non-template friend functions.

    Either you need to provide their definitions within the class definition. Or for each potential template argument of the class you have to define the friend functions outside the class.

    Here is a demonstration program that shows how to define a non-template friend function within the class template definition.

    #include <iostream>
    
    template <typename T>
    class A
    {
    private:
        T t;
    
    public:
        A( const T &t ) : t( t ) {}
    
        friend std::ostream &operator <<( std::ostream &os, const A &a )
        {
            return os << a.t;
        }
    };
    
    
    int main()
    {
        std::cout << A<int>( 10 ) << '\n';
        std::cout << A<const char *>( "Hello" ) << '\n';
    }
    

    The program output is

    10
    Hello
    

    And here is a demonstration program that shows how to define the friend functions outside the class template definition. That is for each used specialization of the class template you need to define the non-template friend functions.

    #include <iostream>
    
    template <typename T>
    class A
    {
    private:
        T t;
    
    public:
        A( const T &t ) : t( t ) {}
    
        friend std::ostream &operator <<( std::ostream &os, const A &a );
    };
    
    
    std::ostream &operator <<( std::ostream &os, const A<int> &a )
    {
        return os << a.t;
    }
    
    std::ostream &operator <<( std::ostream &os, const A<const char *> &a )
    {
        return os << a.t;
    }
    
    int main()
    {
        std::cout << A<int>( 10 ) << '\n';
        std::cout << A<const char *>( "Hello" ) << '\n';
    }
    

    An alternative approach is to declare template friend functions. For example

    #include <iostream>
    
    template <typename T>
    class A
    {
    private:
        T t;
    
    public:
        A( const T &t ) : t( t ) {}
    
        template <typename T>
        friend std::ostream &operator <<( std::ostream &os, const A<T> &a );
    };
    
    template <typename T>
    std::ostream &operator <<( std::ostream &os, const A<T> &a )
    {
        return os << a.t;
    }
    
    int main()
    {
        std::cout << A<int>( 10 ) << '\n';
        std::cout << A<const char *>( "Hello" ) << '\n';
    }