friend声明声明了非模板函数

mik*_*e_b 47 c++ templates operator-overloading friend specialization

我有一个基类类似于下面的代码.我试图重载<<以与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
Run Code Online (Sandbox Code Playgroud)

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

base.h

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

base.cpp

ostream& operator<< (ostream &out, Base<int> *e) {
    out << e->data;
return out;
}
Run Code Online (Sandbox Code Playgroud)

我想在标题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;
}
Run Code Online (Sandbox Code Playgroud)

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

Nat*_*man 34

听起来你想要改变:

friend ostream& operator << (ostream& out, const Base<T>& e);
Run Code Online (Sandbox Code Playgroud)

至:

template<class T>
friend ostream& operator << (ostream& out, const Base<T>& e);
Run Code Online (Sandbox Code Playgroud)

  • 所以我不相信你,但这很有效.但是,我不能使用`T`,因为它'阴影'已经存在的类模板的`T`. (19认同)
  • 所以operator <<(ostream&,const Base <T>&)成为Base <S>的朋友,即使S和T不同?我认为答案应该澄清这一点. (10认同)
  • 是的,海湾合作委员会发出了关于阴影的警告.我用Y替换了T并解决了它.`错误:阴影模板parm'类T'` (8认同)
  • GCC 是否会给您有关阴影的警告? (2认同)
  • 有趣的。我用 Visual Studio 测试了我的答案,它没有阴影问题。但是我可以理解为什么 GCC 可能会发出警告......就像你说的,用另一个模板参数替换 T 将消除阴影。顺便说一句,您的解决方案无法在 MSVC 中编译。 (2认同)

Chu*_*dad 18

Gcc正确警告你.尽管它出现了(它需要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;
}
Run Code Online (Sandbox Code Playgroud)

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

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; 
} 
Run Code Online (Sandbox Code Playgroud)


Ben*_*igt 10

你正在寻找的可能是:

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;
}
Run Code Online (Sandbox Code Playgroud)

这个朋友只有一个模板的实例化,运算符的模板参数与类的模板参数匹配.

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

  • [C++ FAQ](http://www.parashift.com/c++-faq-lite/templates.html#faq-35.16)说类声明中的`friend`行应该有一个`<>`,而不是一个`<T>`. (6认同)
  • 显然你不应该在它之前需要`template <>`行.(目前无法访问编译器,尚未尝试过.) (2认同)

Tyr*_*son 6

改变

friend ostream& operator << (ostream& out, const Base<T>& e);
Run Code Online (Sandbox Code Playgroud)

friend ostream& operator << <T>(ostream& out, const Base<T>& e);
Run Code Online (Sandbox Code Playgroud)

应该也能工作——我只是用这种方式解决了一个相同的问题。