如何正确声明模板类的嵌套类的朋友?

时间:2015-03-11 22:36:29

标签: c++ templates warnings

当我执行以下操作时:

template <typename T>
class Container
{
public:
    class Iterator
    {
        friend bool operator==(const Iterator& x, const Iterator& y);
    };
};

gcc给了我以下警告和建议:

warning: friend declaration 
'bool operator==(const Container<T>::Iterator&, 
                 const Container<T>::Iterator&)' 
declares a non-template function [-Wnon-template-friend]

friend bool operator==(const Iterator& x, const Iterator& y);
                                                           ^

(if this is not what you intended, 
 make sure the function template has already been declared 
 and add <> after the function name here)

我很确定这是一个新警告,因为我一直这样做,从来没有遇到过任何问题。

有人可以解释为什么这是一个警告,它警告什么?

2 个答案:

答案 0 :(得分:6)

它警告说,实际上不可能在课外定义operator==

也就是说,friend声明与非模板operator==函数成为朋友 - 例如,Container<Int>::Iterator具有作为朋友的函数

bool operator==(const Container<Int>::Iterator&, const Container<Int>::Iterator&);

此函数不是模板,因此几乎无法为类模板定义之外的所有可能operator==定义Container。< / p>

如果您尝试

template<class T>
bool operator==(const Container<T>::Iterator&, const Container<T>::Iterator&);

这是一个功能模板,与朋友声明不匹配。 (在这种情况下,它更糟糕,因为你可以实际使用此运算符,因为T处于非推导的上下文中。)

警告消息提示了一种可能的解决方法 - 首先声明一个函数模板,然后与它进行特化。 (您需要将Iterator从类中拉出到自己独立的类模板中,以便可以推导出T。)另一种可能的解决方法是在类模板中定义函数定义

答案 1 :(得分:4)

声明

friend bool operator==(const Iterator& x, const Iterator& y);

在最近的封闭命名空间范围内声明非模板函数,该范围采用类型为const typename Container<T>::Iterator&的两个参数。因此,每次实例化类Container时,使用一些模板参数T,都会声明operator==的新重载

由于此operator==未从模板实例化,因此您无法将其定义为模板外的。因此,定义此声明的operator==的唯一方法是为实例化Container的每种类型单独定义它。这几乎肯定是不可取的。

警告警告您,您声明的朋友不是模板,这会产生我刚才解释过的不良后果。

我相信你正在尝试做的事情的正确方法如下:

template <typename T>
class Container_Iterator;

template <typename T> bool operator==(const Container_Iterator<T>& x,
                                      const Container_Iterator<T>& y);

template <typename T>
class Container
{
public:
    typedef Container_Iterator<T> Iterator;
};

template <typename T>
class Container_Iterator {
  friend bool operator==<T>(const Container_Iterator<T>& x,
                            const Container_Iterator<T>& y);
};

// btw, don't forget to define operator==

现在我们显式地将operator==声明为模板,并且迭代器的每个特化都声明operator==作为其朋友的相应特化。