简体   繁体   中英

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 !

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 (eg &ns::operator<< doesn't work, unlike the other options) and they are only found via ADL.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM