8

我在重载<<流运算符时遇到问题,但找不到解决方案:

template<class T, unsigned int TN>
class NVector
{
    inline friend std::ostream& operator<< (
        std::ostream &lhs, const NVector<T, TN> &rhs);
};

template<class T, unsigned int TN>
inline std::ostream& NVector<T, TN>::operator<<(
    std::ostream &lhs, const NVector<T, TN> &rhs)
{
    /* SOMETHING */
    return lhs;
};

它产生以下错误消息:

警告:朋友声明 'std::ostream& operator<<(std::ostream&, const NVector&)' 声明了一个非模板函数 [-Wnon-template-friend]

错误:'std::ostream& NVector::operator<<(std::ostream&, const NVector&)' 必须只采用一个参数

如何解决这个问题?

非常感谢你。

4

1 回答 1

16

您的代码中有两个不同的问题,第一个是friend声明(正如警告明确指出的那样,可能不太清楚)将单个非模板化函数声明为友元。也就是说,当您实例化模板时NVector<int,5>,它会将非模板化函数声明std::ostream& operator<<(std::ostream&,NVector<int,5>)为友元。请注意,这与声明您作为朋友提供的模板函数不同。

我建议您在类定义中定义朋友函数。您可以在此答案中阅读更多相关信息。

template <typename T, unsigned int TN>
class NVector {
   friend std::ostream& operator<<( std::ostream& o, NVector const & v ) {
      // code goes here
      return o;
   }
};

或者,您可以选择其他选项:

  1. 将模板声明operator<<为友元(将授予对模板的任何和所有实例的访问权限),
  2. 将该模板的特定实例声明为友元(编写起来更麻烦)或
  3. 完全避免友谊,提供公共print( std::ostream& )成员函数并从非朋友模板调用它operator<<。我仍然会选择与非模板函数成为朋友,并在模板类中提供定义。

第二个问题是,当您想在左侧参数的类之外定义运算符时,该运算符是一个自由函数(未绑定到类),因此它不应该被限定:

template<class T, unsigned int TN>
inline std::ostream& operator<<(std::ostream &lhs, const NVector<T, TN> &rhs)
{
    /* SOMETHING */
    return lhs;
};
于 2012-05-28T16:27:14.227 回答