Reputation: 60451
What is the correct way to declare a friend function of a template class (for the std::ostream& operator<<) in a .cpp file ?
My current implementation does not work :
// MyTest.h
template<class T, unsigned int TSIZE> class MyTest
{
inline friend std::ostream& operator<< <T, TSIZE> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs);
};
// MyTest.cpp
template<class T, unsigned int TSIZE> inline friend std::ostream& operator<< <T, TSIZE> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs)
{
// IMPLEMENTATION
}
Upvotes: 5
Views: 1708
Reputation: 35459
To refer to operator<< <T, TSIZE>
like you do, which is a template specialization, a declaration of the primary template must be visible. In turn operator<<
needs a declaration of MyTest
because it appears as a parameter.
// Declare MyTest because operator<< needs it
template<class T, unsigned int TSIZE> class MyTest;
// Declare primary template
template<class T, unsigned int TSIZE>
inline std::ostream& operator<<(std::ostream& lhs, const MyText<T, TSIZE>& rhs);
template<class T, unsigned int TSIZE> class MyTest
{
// Specialization MyTest<T, TSIZE> only declares
// specialization operator<< <T, TSIZE> as friend
// Note that you can just use '<>' to designate the specialization,
// template parameters are deduced from the argument list in this case
inline friend std::ostream& operator<< <> (std::ostream &lhs, const MyTest<T, TSIZE> &rhs);
};
The definition you have should match those declarations. Note that since operator<<
is a template its definition should in all likeliness be in the header.
An alternative that requires less work when it comes to writing all those preemptive declarations is for MyTest<T, TSIZE>
to declare the whole template as a friend, not just the specialization that takes MyTest<T, TSIZE>
.
// in MyTest definition
template<typename U, unsigned USIZE>
inline friend std::ostream& operator<<(std::ostream& lhs, const MyTest<U, USIZE>& rhs);
The definition you have should also match such a declaration (the name of the template parameters has no bearing on matching declarations and definition).
For the sake of completeness, I will mention that when it comes to the friend of a class template an alternative is to define it in the class template definition. This defines a non-template friend function that is unique for each specialization.
// in MyTest definition
friend std::ostream& operator<<(std::ostream& lhs, MyTest const& rhs)
{ /* implementation */ }
It is impossible to refer to such functions (e.g. &ns::operator<<
doesn't work, unlike the other options) and they are only found via ADL.
Upvotes: 8
Reputation: 10557
It is not fully clear what the original post wanted. I will assume that it wanted the following:
// Some template class.
template<class T, unsigned int TSIZE> class MyTest { };
// Some template function.
template<class T, unsigned int TSIZE> std::ostream& operator<< (std::ostream &lhs, const MyTest<T, TSIZE> &rhs)
{
// IMPLEMENTATION
}
Now it is necessary to declare this template function as friend of the class because this function needs access to protected objects of My test
. This can be achieved with the following definition:
template<class T, unsigned int TSIZE> class MyTest
{
template<class T1, unsigned int TSIZE1>
friend std::ostream& operator<< (std::ostream &lhs, const MyTest<T1, TSIZE1> &rhs);
};
Template header is needed in front of the friend
declaration because this is an unrelated template function, that does not belong to the current template class.
Upvotes: 0