C++ : friend declaration ‘declares a non-template function
Asked Answered
B

1

10

I have a problem to overload the << stream operator and I don't find the solution :

template<class T, unsigned int TN>
class NVector
{
    inline friend std::ostream& operator<< (
        std::ostream &lhs, const NVector<T, TN> &rhs);
};

template<class T, unsigned int TN>
inline std::ostream& NVector<T, TN>::operator<<(
    std::ostream &lhs, const NVector<T, TN> &rhs)
{
    /* SOMETHING */
    return lhs;
};

It produces the following error message:

warning : friend declaration ‘std::ostream& operator<<(std::ostream&, const NVector&)’ declares a non-template function [-Wnon-template-friend]

error: ‘std::ostream& NVector::operator<<(std::ostream&, const NVector&)’ must take exactly one argument

How to solve that problem ?

Thank you very much.

Bobsledding answered 28/5, 2012 at 16:20 Comment(1)
A friend is not a member, and operator<< should not be a member. Remove the resolution in the definition header.Eponym
L
18

There are two different issues in your code, the first is that the friend declaration (as the warning clearly says, maybe not so clear to understand) declares a single non-templated function as a friend. That is, when you instantiate the template NVector<int,5> it declares a non-templated function std::ostream& operator<<(std::ostream&,NVector<int,5>) as a friend. Note that this is different from declaring the template function that you provided as a friend.

I would recommend that you define the friend function inside the class definition. You can read more on this in this answer.

template <typename T, unsigned int TN>
class NVector {
   friend std::ostream& operator<<( std::ostream& o, NVector const & v ) {
      // code goes here
      return o;
   }
};

Alternatively you can opt for other options:

  1. declare the operator<< template as a friend (will grant access to any and all instantiations of the template),
  2. declare a particular instantiation of that template as a friend (more cumbersome to write) or
  3. avoid friendship altogether providing a public print( std::ostream& ) member function and calling it from a non-friend templated operator<<. I would still opt to befriend the non-template function an provide the definition inside the templated class.

The second issue is that when you want to define an operator outside of the class of the left hand side argument, the operator is a free function (not bound to a class) and thus it should not be qualified:

template<class T, unsigned int TN>
inline std::ostream& operator<<(std::ostream &lhs, const NVector<T, TN> &rhs)
{
    /* SOMETHING */
    return lhs;
};
Lustral answered 28/5, 2012 at 16:27 Comment(1)
If any body is looking why there damn warning sticks around even though that's exactly what they want to do: #71230935 Basically option 2. is the only viable one, even if it's uglyShortsighted

© 2022 - 2024 — McMap. All rights reserved.