Search code examples
c++templatesnamespacesoperatorsfriend

Define friend template method outside namespace


I have code with the following basic structure:

namespace A{

    template<class T,unsigned DIM>
    class CMyTable{
        ...
            public:
            template<class T,unsigned DIM>
            friend std::ostream& operator<<(std::ostream& s, const CMyTable<T,DIM>& vec);
        }    

    };

}

The initial problem was to get my operator<< outside the namespace A.

I tried this solution : How do I define friends in global namespace within another C++ namespace?

namespace A{

    template<class T,unsigned DIM>
    class CMyTable;
}

template<class T,unsigned DIM>
std::ostream& operator<<(std::ostream& s, const CMyTable<T,DIM>& vec);

namespace A{

    template<class T,unsigned DIM>
    class CMyTable{
        ...
            public:
            template<class T,unsigned DIM>
            friend std::ostream& ::operator<<(std::ostream& s, const CMyTable<T,DIM>& vec);
        }    

    };

}

template<class T,unsigned DIM>
std::ostream& operator<<(std::ostream& s, const CMyTable<T,DIM>& vec){
// [...]
}

I got this error : error C2063: 'operator <<' : not a function inside the class declaration.

public:
template<class T,unsigned DIM>
friend std::ostream& ::operator<<(std::ostream& s, const CMyTable<T,DIM>& 

Does anyone have any ideas ?

Thanks.


Solution

  • If your ostream overload has to be a friend (needs access to protected members) then define it inline so that you can use the template arguments passed to the class.

    namespace A{
    
        template<class T,unsigned DIM>
        class CMyTable{
            ...
            public:
            // template<class T,unsigned DIM>  // This will shadow otherwise
            friend std::ostream& operator<<(std::ostream& s, const CMyTable<T,DIM>& vec) {
            // [...]
            }
        };
    }
    

    Otherwise completely remove its declaration from the class and namesapce and just define it outside as a templated overload.

    Remember it doesn't have to be friend if it doesn't need access to private or protected elements.

    namespace A{
       template<class T,unsigned DIM>
       class CMyTable{
        ...
            public:
        };
    }
    
    
    
    template<class T,unsigned DIM>
    std::ostream& operator<<(std::ostream& s, const A::CMyTable<T,DIM>& vec){
    // [...]
    }
    

    The third option is to keep it friend but define it inside namespace A

    namespace A{
    
        template<class T,unsigned DIM>
        class CMyTable{
            public:
                int i;
    
            template<class V,unsigned E>
            friend std::ostream& operator<<(std::ostream& s, const CMyTable<V,E>& vec);
        };  
    
    };
    //
    //
    
    namespace A{
    
        template<class T,unsigned DIM>
        std::ostream& operator<<(std::ostream& s, const CMyTable<T,DIM>& vec) {
            s << vec.i;
        }
    
    }