What is the right way to write friend function declarations in template class?

c++, friend, templates, vector

Solution

Friend non-template function

But the compiler reports a warning that I declare a non-template function.

Yes, you're declaring a non-template function inside the class definition. That means if you define it out of the class definition, you have to define it as non-template function, and for all the possible instantiations , like:

bool operator==(const vector<int>& v1, const vector<int>& v2)
{
    ...
}
bool operator==(const vector<char>& v1, const vector<char>& v2)
{
    ...
}

That is ugly, you can define it inside the class definition like

template <typename T, typename Alloc = std::allocator<T>>
class vector {
public:
    friend bool operator==(const vector<T, Alloc>&, const vector<T, Alloc>&) {
        ...
    }
};

Friend function template

If you want to define it as template function, and constrain the scope of friendship, you can

// forward declaration
template <typename T, typename Alloc>
class vector;

// forward declaration
template <typename T, typename Alloc>
bool operator==(const vector<T, Alloc>& v1, const vector<T, Alloc>& v2);

template <typename T, typename Alloc = std::allocator<T>>
class vector {
private:
    int i;
public:
    // only the instantiation of operator== with template parameter type of current T and Alloc becomes friend
    friend bool operator==<>(const vector<T, Alloc>& v1, const vector<T, Alloc>& v2);
};

template <typename T, typename Alloc = std::allocator<T>>
bool operator==(const vector<T, Alloc>& v1, const vector<T, Alloc>& v2)
{
    ...
}

Then, for `vector<int>`, only `bool operator==(const vector<int>&, const vector<int>&)` is friend, other instantiations like `bool operator==(const vector<double>&, const vector<double>&)` is not.

LIVE

Problem

I'm trying to write my own vector template class, but I have some problems when writing friend function declarations. At first I wrote like this: ``` template <typename T, typename Alloc = std::allocator<T>> class vector { public: friend bool operator==(const vector<T, Alloc>&, const vector<T, Alloc>&); }; ``` But the compiler reports a warning that I declare a non-template function. So I changed the friend declaration to this: ``` template <typename T, typename Alloc = std::allocator<T>> class vector { public: template <typename E, typename F> friend bool operator==(const vector<E, F>&, const vector<E, F>&); }; ``` So far everything is fine, but I think there are still problems. If I write like that, I make all `operator==` functions which take two template arguments as its friend functions. For example, `operator==(const vector<int>&, const vector<int>&)` and `operator==(const vector<double>&, const vector<double>&)` would both be `vector<int>`'s friend function. What is the right way to write friend functions in template class?

Original source