Hello World

C++ 类模板友元函数

问题来源

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

template<class T>
A<T> operator + (const A<T>& , const A<T>&);

template <class T>
A<T> operator+ (A<T> & a1, A<T> & a2){
//... whatever
}

template <class T>
class A{
friend A<T> operator +<> (const A<T>& , const A<T>& );
private: //...whatever
public: //...whatever
}

运行正常

Problem 1 对友元声明的修改

但去掉 class A友元声明中operator +<>中的<>,
即友元声明变为 friend A<T> operator + (const A<T>& , const A<T>& );
则程序仍可运行,但出现
warning: friend declaration 'A<T> operator+(const A<T>&, const A<T>&)' declares a non-template function

Problem 2 对函数声明进行修改

不进行 problem1 中的友元声明更改,但去掉模板重载运算符的声明,
即代码变为

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

// 去掉 template<class T>
// 去掉 A<T> operator + (const A<T>& , const A<T>&);

template <class T>
A<T> operator+ (A<T> & a1, A<T> & a2){
//... whatever
}

template <class T>
class A{
friend A<T> operator +<> (const A<T>& , const A<T>& );
private: //...whatever
public: //...whatever
}

程序报错:
error: template-id 'operator+<>' for 'A<int> operator+(const A<int>&, const A<int>&)' does not match any template declaration|

Problem 3 同时更改类中友元声明和去掉模板重载运算符声明

即同时进行 Problem 2 和 Problem 3 中的修改,程序可以运行,但出现
warning: friend declaration 'A<T> operator+(const A<T>&, const A<T>&)' declares a non-template function (与Prolem 1相同)

问题分析

在stack overflow 上问了这个问题,解答如下:

Case 1

friend A operator +<> (const A& , const A& ) is actually a friend specialization of following function for type T (which is class template’s type).

1
2
template<class T>
A<T> operator + (const A<T>& , const A<T>&);

If you want to specialize this function for a specific type like int you do like this:

1
2
3
4
template<>
A<int> operator+(const A<int>&, const A<int>&)
{
}

So your friend function is a specialized friend function.

when you remove <> your friend function turn into a normal friend function but your actual operator+ is a template function. compiler is warning you because your class definition has a non-template declaration of the friend function (without the template), but the friend function definition is a function template. Change your friend function to the following to suppress warning.

1
2
template<class T1>
friend A<T1> operator+ (const A<T1>&, const A<T1>&);

Case 2

You get that error because your deceleration and definition of operator +differ in const qualifier for parameters. Actually they are completely two different function that second function isn’t definition of the first one. Add const to the parameters of your function definition.

Indeed when you remove this code:

1
2
template<class T>
A<T> operator + (const A<T>& , const A<T>&);

Compiler can’t found a template function for your friend deceleration that take two const A& parameter.