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

时间:2010-10-21 16:25:00

标签: 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);
};

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 ++编译了代码,很好,没有任何警告。

3 个答案:

答案 0 :(得分:30)

这只是对该语言棘手方面的警告。当您声明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);
};

答案 1 :(得分:3)

这是一个相当古老的主题,但我认为声明运算符的最简单方法是在Float类中定义它。

template<int E, int F>
class Float
{
public:
    friend Float operator+ (const Float &lhs, const Float &rhs)
    {
        // Whatever you need to do.
    }
};

语法更易于编写和理解,并且它将完全相同(除了它将被内联),它将不是成员函数。

  

MSDN:在类声明中定义的友元函数不在封闭类的范围内考虑;他们在文件范围内。

答案 2 :(得分:1)

您需要完全按照警告说:

template<int E, int F>
Float<E, F> operator+ (const Float<E, F> &lhs, const Float<E, F> &rhs);

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

这声明了操作员模板的完全特化,是模板的特定实例的朋友。在对UncleBens问题的评论中,我很友好地提供了a link to an explanation为什么这么复杂。