Friend function inside template class
Kexin Tang

Assume we have a template class named Matrix, and we want to add a friend function called swap().

Method 1

1
2
3
4
5
6
7
template<typename T>
class Matrix {
// ...
friend void swap(Matrix<T>& a, Matrix<T>& b) {
// definition
}
};

Notice, the swap() is not a template function! It’s just a normal function.

Why we need to define it inside the class?

Because when we create a Matrix<int>, it will also define a void swap(Matrix<int>&, Matrix<int>&) for system; for Matrix<double>, it’s the same. In other word, when we create certain type Matrix, the swap which supports that certain type will be automatically created for us. So that when we use swap(), it always make sure we can find the definition.

Can we define it outside the class?

Yes, you can, but you need to make sure you write definitions for all possible types, like you need to implement a void swap(Matrix<int>&, Matrix<int>), a void swap(Matrix<double>&, Matrix<double>), etc for all possible typename T.

Method 2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
template<typename T>
class Matrix;

template<typename T>
void swap(Matrix<T>&, Matrix<T>&); // we need to know what is Matrix<T>, so declare Matrix before

template<typename T>
class Matrix {
// ...
friend void swap<>(Matrix& a, Matrix& b); // we need to know that is a template function, so declare before
};

template<typename T>
void swap(Matrix<T>& a, Matrix<T>& b) {
// definition
}

Notice here the swap is a template function, so that we need to write it as swap<>, and we don’t need to explicitly denote Matrix type, cuz template funtion can deduce its type.

Can we don’t write the declarition of template swap?

No. Inside class definition, we tell the class that we have a template friend function. If we don’t declare it before class definition, the class don’t know how many typenames it has, do it have default typename, etc.

Trick

1
2
3
4
5
6
7
template<typename T> void helper(T);

template<typename T>
class Obj {
// ...
friend void helper<char>(char); // no matter what type Obj is, only helper with char type can get access to private members
}