Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ : friend function in a template class for operator<<

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 !

like image 894
Vincent Avatar asked Jul 30 '12 04:07

Vincent


People also ask

Can we declare a template function as the friend of the class?

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.

Can operator function be a friend?

Operator function must be either non-static (member function) or friend function.

Can a friend function be defined within a class?

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).

How do you declare a friend function outside the class?

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); };


1 Answers

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.

like image 71
Luc Danton Avatar answered Sep 27 '22 20:09

Luc Danton