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
}
Thank you very much !
One-to-one: A template function instantiated with one set of template arguments may be a friend to one template class instantiated with the same set of template arguments. This is also the relationship between a regular non-template class and a regular non-template friend function.
Operator function must be either non-static (member function) or friend function.
Friend functions can be defined (given a function body) inside class declarations. These functions are inline functions. Like member inline functions, they behave as though they were defined immediately after all class members have been seen, but before the class scope is closed (at the end of the class declaration).
Syntax of friend functions: To make a function that is declared outside the class “friendly” to that class, we have to declare the function as a friend function, as seen below: class className{ // Other Declarations friend returnType functionName(arg list); };
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With