C++模板的朋友操作符重载

Zif*_*ong 11 c++ templates operator-overloading friend

我的代码出了什么问题?

template<int E, int F>
class Float
{
 friend Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs);
};
Run Code Online (Sandbox Code Playgroud)

G ++只是警告:

float.h:7: warning: friend declaration ‘Float<E, F> operator+(const Float<E, F>&, const Float<E, F>&)’ declares a non-template function

float.h:7: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning

我试着add <> after the function name here在警告说明中提到,但是g ++给了我一个错误.

我用clang ++编译代码,很好,没有任何警告.

Pot*_*ter 32

这只是对该语言棘手方面的警告.声明friend函数时,它不是声明所在类的成员.为方便起见,可以在那里定义它,但它实际上属于命名空间.

在类模板中声明不是模板的友元函数仍然在命名空间中声明非模板函数.它既不是类的成员,也不是模板.但是,它是由类模板生成的.

从模板生成非模板函数有点模糊.例如,您无法在class块外添加该函数的声明.因此,您必须在class块内定义它,这是有道理的,因为类模板将生成它.

关于朋友的另一个棘手的事情是内部的声明class Float {}不会在命名空间中声明该函数.您只能通过依赖于参数的意义重载解析来找到它,即指定参数具有类型Float(或引用或指针).这不是问题operator+,因为它可能会过载,除了用户定义的类型之外永远不会被调用.

有关潜在问题的示例,请假设您有一个转换构造函数Float::Float( Bignum const& ).但Bignum没有operator+.(对不起,人为的例子.)你想依靠operator+(Float const&, Float const&)Bignum加法.现在my_bignum + 3不会编译,因为两个操作数都不是,Float所以它找不到该friend函数.

可能你没有什么可担心的,只要有问题的功能是operator.

或者,您也可以将其更改friend为模板.在这种情况下,它必须在块之外定义class {},并在它之前声明,而不是需要在内部声明和定义.

template<int E, int F> // now this is a template!
Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs);

template<int E, int F>
class Float
{
  // deduce arguments E and F - this names operator+< E, F >.
 friend Float<E, F> operator+<> (const Float<E, F> &lhs, const Float<E, F> &rhs);
};
Run Code Online (Sandbox Code Playgroud)