朋友声明声明了一个非模板函数[重复]

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&) 成为 Base 的朋友,即使 S 和 T 不同?我认为答案应该澄清这一点。【参考方案2】:

Gcc 正确地警告你。尽管它的外观(它需要 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; 
 

【讨论】:

好吧,使用&lt;&lt; 运算符永远不会找到任何带有U != T 的实例化。不过,直接调用可能会,这真的很奇怪。只有operator &lt;&lt;Base&lt;U&gt; 访问了Base&lt;T&gt; 类型的全局变量才有意义。 @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 行应该有一个&lt;&gt;,而不是&lt;T&gt; 显然你不应该在它之前需要template&lt;&gt; 行。 (暂时无法访问编译器,没试过。) 我相信原来的错误信息是建议public: friend ostream&amp; operator &lt;&lt; &lt;&gt;(ostream &amp;, const Base&lt;T&gt; &amp;);【参考方案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,但我看到了更完整的答案,所以我会修改它们。

以上是关于朋友声明声明了一个非模板函数[重复]的主要内容,如果未能解决你的问题,请参考以下文章

模板类中的非模板函数[关闭]

C++中的朋友和模板

[转]C++函数模板与模板函数

[c++][语言语法]函数模板和模板函数

在不知道其模板参数的情况下将类模板声明为朋友的最佳方法

C++中,怎么将函数模板的声明和定义分开写?