56

我有一个类似于下面代码的基类。我正在尝试重载 << 以与 cout 一起使用。但是,g++ 说:

base.h:24: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, Base<T>*)’ declares a non-template function
base.h:24: 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

我尝试在类声明/原型中的 << 之后添加 <>。但是,我明白了does not match any template declaration。我一直在尝试将运算符定义完全模板化(我想要),但我只能让它与以下代码一起使用,并手动实例化运算符。

基础.h

template <typename T>
class Base {
  public:
    friend ostream& operator << (ostream &out, Base<T> *e);
};

基础.cpp

ostream& operator<< (ostream &out, Base<int> *e) {
    out << e->data;
return out;
}

我想在标头base.h中包含这个或类似的:

template <typename T>
class Base {
  public:
    friend ostream& operator << (ostream &out, Base<T> *e);
};

template <typename T>
ostream& operator<< (ostream &out, Base<T> *e) {
    out << e->data;
return out;
}

我在网上其他地方读到,在原型中将 <> 放在 << 和 () 之间应该可以解决这个问题,但事实并非如此。我可以把它变成一个单一的功能模板吗?

4

6 回答 6

39

听起来你想改变:

friend ostream& operator << (ostream& out, const Base<T>& e);

到:

template<class T>
friend ostream& operator << (ostream& out, const Base<T>& e);
于 2010-10-28T04:58:58.400 回答
22

Gcc 正确地警告你。尽管它的外观(它需要 Base 参数),但它不是函数模板。

您的类定义有一个友元函数的非模板声明(没有模板),但后来的友元函数定义是一个函数模板(即以模板开头..)。

你的 operator<< 也需要一个 Base *。这是不正确的。它应该是 Base const & 以保留它的内置语义

可能您正在查看以下内容:

template <typename T> 
class Base { 
  public: 
    friend ostream& operator << (ostream &out, Base<T> const &e){
       return out;
    }; 
}; 

int main(){
   Base<int> b;
   cout << b;
}

如果您想要完全模板化,那么这可能就是您想要的。但我不确定这比前一个有多大用处。由于查找涉及 ADL,因此您将永远无法解决 T 不等于 U 的任何条件(只要调用来自与此类无关的上下文,例如来自“主”函数)

template <typename T>  
class Base {  
  public:  
    template<class U> friend ostream& operator << (ostream &out, Base<U> const &e){ 
       return out; 
    };  
};

int main(){ 
   Base<int> b; 
   cout << b; 
} 
于 2010-10-28T05:00:05.550 回答
9

可能您正在寻找的是:

template <typename T>
class Base;

template <typename T>
ostream& operator<< (ostream &, const Base<T>&);

template <typename T>
class Base
{
  public:
    template<>
    friend ostream& operator << <T>(ostream &, const Base<T> &);
};

template <typename T>
ostream& operator<< ( ostream &out, const Base<T>& e )
{
    return out << e->data;
}

这仅适用于模板的单个实例化,即运算符的模板参数与类的模板参数匹配的实例。

更新:不幸的是,这是非法的。MSVC 和 Comeau 都拒绝它。这就提出了为什么原始错误消息几乎完全建议这种方法的问题。

于 2010-10-28T05:08:21.500 回答
6

改变

friend ostream& operator << (ostream& out, const Base<T>& e);

friend ostream& operator << <T>(ostream& out, const Base<T>& e);

应该也可以——我刚刚以这种方式解决了一个相同的问题。

于 2012-12-13T15:06:32.577 回答
0

改变

friend ostream& operator << (ostream &out, Base<T> *e)`

template<T> friend ostream& operator << (ostream &out, Base *e)
于 2017-03-04T07:47:20.823 回答
-3

改变

ostream& operator<< (ostream &out, Base<int> *e) {
    out << e->data;
    return out;
}

ostream& operator<< (ostream &out, T *e) {
    out << e->data;
    return out;
}
于 2010-10-28T04:46:44.070 回答