朋友声明声明了一个非模板函数[重复]
Posted
技术标签:
【中文标题】朋友声明声明了一个非模板函数[重复]【英文标题】:friend declaration declares a non-template function [duplicate] 【发布时间】:2011-05-01 16:31:15 【问题描述】:我有一个类似于下面代码的基类。我正在尝试重载
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
。我一直在尝试将运算符定义完全模板化(我想要),但我只能让它与以下代码一起使用,并手动实例化运算符。
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;
我只想在标头 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;
我在网上其他地方读到,在原型中将 放在
【问题讨论】:
这正是 Dan Saks 的"Making New Friends" idiom 解决的问题。 (对不起,迟到的评论。) 我已经链接到另一个问题的答案,该答案详细解释了为什么建议的修复是必要的/工作 【参考方案1】:听起来你想改变:
friend ostream& operator << (ostream& out, const Base<T>& e);
收件人:
template<class T>
friend ostream& operator << (ostream& out, const Base<T>& e);
【讨论】:
所以我不相信你,但这有效。但是,我不能使用T
,因为它shadows
是类模板中已经存在的T
。
GCC 是否会给您关于阴影的警告?
是的,GCC 发出了关于阴影的警告。我用 Y 替换了 T 并解决了它。 error: shadows template parm ‘class T’
有趣。我用 Visual Studio 测试了我的答案,它没有阴影问题。但我明白为什么 GCC 可能会发出警告......就像你说的那样,用另一个模板参数替换 T 将消除阴影。顺便说一句,Ben,您的解决方案无法在 MSVC 中编译。
所以 operator&) 成为 BaseGcc 正确地警告你。尽管它的外观(它需要 Base 参数),但它不是函数模板。
你的类定义有一个友元函数的非模板声明(没有模板),但后来的友元函数定义是一个函数模板(即以模板开头..)。
你的操作符
您可能正在查看以下内容:
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;
【讨论】:
好吧,使用<<
运算符永远不会找到任何带有U != T
的实例化。不过,直接调用可能会,这真的很奇怪。只有operator <<
的Base<U>
访问了Base<T>
类型的全局变量才有意义。
@Ben Voigt:只要调用来自与此类无关的上下文,就添加了 ' 部分。从'主要'功能'。希望现在更清楚
为了完整起见,可能会在类定义之外添加如何定义友元函数?【参考方案3】:
您可能正在寻找的是:
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 都拒绝它。这就提出了为什么原始错误消息几乎完全建议这种方法的问题。
【讨论】:
C++ FAQ 表示类声明中的friend
行应该有一个<>
,而不是<T>
。
显然你不应该在它之前需要template<>
行。 (暂时无法访问编译器,没试过。)
我相信原来的错误信息是建议public: friend ostream& operator << <>(ostream &, const Base<T> &);
【参考方案4】:
变化
friend ostream& operator << (ostream& out, const Base<T>& e);
到
friend ostream& operator << <T>(ostream& out, const Base<T>& e);
应该也可以——我只是用这种方式解决了一个相同的问题。
【讨论】:
【参考方案5】:变化
friend ostream& operator << (ostream &out, Base<T> *e)`
到
template<T> friend ostream& operator << (ostream &out, Base *e)
【讨论】:
【参考方案6】:改变
ostream& operator<< (ostream &out, Base<int> *e)
out << e->data;
return out;
到
ostream& operator<< (ostream &out, T *e)
out << e->data;
return out;
【讨论】:
这绝对行不通。除了提供employee.cpp:32: error: ‘T’ was not declared in this scope
,即使在.h 或.cpp 文件中将其设为模板后,由于链接期间未定义符号,它也无法工作。此外,我仍然收到警告。我希望它像头文件中定义的普通模板一样。
那时我完全错过了 Base 课程。应该只是 T,但我看到了更完整的答案,所以我会修改它们。以上是关于朋友声明声明了一个非模板函数[重复]的主要内容,如果未能解决你的问题,请参考以下文章