C++ 友元声明声明了一个非模板函数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4039817/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:21:13  来源:igfitidea点击:

friend declaration declares a non-template function

c++templatesoperator-overloadingfriendspecialization

提问by mike_b

I have a base Class akin to the code below. I'm attempting to overload << to use with cout. However, g++ is saying:

我有一个类似于下面的代码的基类。我正在尝试重载 << 以与 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

I've tried adding <> after << in the class declaration / prototype. However, then I get it does not match any template declaration. I've been attempting to have the operator definition fully templated (which I want), but I've only been able to get it to work with the following code, with the operator manually instantiated.

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

base.h

基数

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

base.cpp

基本文件

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

I want to just have this or similar in the header, base.h:

我只想在标题 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;
}

I've read elsewhere online that putting <> between << and () in the prototype should fix this, but it doesn't. Can I get this into a single function template?

我在网上的其他地方读过,在原型中将 <> 放在 << 和 () 之间应该可以解决这个问题,但事实并非如此。我可以将其放入单个函数模板中吗?

采纳答案by Nathan Pitman

It sounds like you want to change:

听起来你想改变:

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

To:

到:

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

回答by Chubsdad

Gcc is rightly warning you. Despite it's appearances (it takes Base argument), it is not a function template.

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

Your class definition has a non-template declaration of the friend function (without the template), but the friend function definition later on is a function template (i.e. starts with template..).

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

Also your operator<< takes a Base *. This is not correct. It should be Base const & to retain it's built-in semantics

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

Probably you are looking at something as below:

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

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

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

If you want fully templated, then this is probably what you want. But I am not sure how much useful this is over the previous one. Since the lookup involves ADL, you will never be able to resolve to any condition where T is not equal to U (as long as the call is from a context not related to this class e.g. from 'main' function)

如果您想要完全模板化,那么这可能就是您想要的。但我不确定这比前一个有用多少。由于查找涉及 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; 
} 

回答by Ben Voigt

Probably what you are looking for is:

可能你正在寻找的是:

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;
}

This friends only a single instantiation of the template, the one where the operator's template parameter matches the class's template parameter.

这只是模板的一个实例化,即运算符的模板参数与类的模板参数匹配的实例。

UPDATE: Unfortunately, it's illegal. Both MSVC and Comeau reject it. Which raises the question of why the original error message suggested pretty much EXACTLY this approach.

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

回答by Tyrone Hinderson

changing

改变

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

to

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

should work as well--I just solved an identical problem in this way.

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

回答by Elías Arriaga

changing

改变

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

To

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

回答by Bruce Armstrong

change

改变

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

to

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