Befriending Function Templates
Syntactically speaking, declaring function templates as friends is the most complex part in this trilogy. Let's look at a concrete example. Suppose you have a class template called Vector. You want to declare the overloaded
operator== function template as a friend of Vector. Consequently, for every
Vector<T>, the compiler shall generate a matching
operator==<T>. Such a declaration is done in three steps.
First, forward declare both the class template granting friendship and the function template:
template <typename T> class Vector;
// forward declaration of function template operator==
template <typename T>
bool operator== (const Vector<T>& v1,
const Vector<T>& v2);
Next, declare the function template as a friend inside the class template:
template <typename T> class Vector
{
public:
friend bool operator==<T> (const Vector<T>& v1,
const Vector<T>& v2);
};
Finally, define the function template:
template <typename T>
bool operator==(const Vector<T>& v1,
const Vector<T>& v2)
{
//...
}
Vector<int> vi,vi2;
bool b= vi==vi2;
This seems like a lot of work for a single friend declaration. You can collapse these three steps into one by moving the definition of the befriended function into the friend declaration:
template <typename T> class Vector
{
public:
//defining the friend function template inside the class
friend bool operator== (const Vector<T>& v1,
const Vector<T>& v2)
{
//..
}
};
In the overloaded
operator== and
class Vector<T>, the parameter
T co-varies, which means that the compiler generates
operator==<int> for
Vector<int>,
operator==<bool> for
Vector<bool>, etc. Don't let the syntax mislead you though: a function defined within a friend declaration is never a member function of the enclosing class. It's an ordinary freestanding function.
You may declare a specialization of a function template as a friend. To do so, forward declare the class template and the function template, as before. Then include a friend declaration inside class Vector:
template <typename T> class Vector;
template <typename T>
bool operator==(const Vector<T> &v1,
const Vector<T>& v2 );
template <typename T> class Vector
{
public:
friend bool operator==<int> (const Vector<int>& v1,
const Vector<int>& v2);
};
The difference between this declaration and the former one is that the template argument (
int in this case) appears in angle brackets after the function's name and instead of the template parameter
T, in the function's parameters list.
Finally, define the specialization of the function template in question:
template <> bool //specialization definition
operator==<int> (const Vector<int>& v1,
const Vector<int>& v2)
{
//..
}
Recall that a definition of a specialization is preceded by the sequence
template <>. Note also that a specialization of a function template cannot be defined within a friend declaration.