[英]warning defining friend operator declared inside a namespace
有人可以向我解释来自 g++ 的警告吗?
鉴于以下代码
#include <iostream>
namespace foo
{
struct bar
{ friend std::ostream & operator<< (std::ostream &, bar const &); };
}
std::ostream & foo::operator<< (std::ostream & o, foo::bar const &)
{ return o; }
int main ()
{
foo::bar fb;
std::cout << fb;
}
我得到(来自 g++ (6.3.0) 但不是来自 clang++ (3.8.1) 而不是(感谢 Robert.M)来自 Visual Studio(2017 社区))这个警告
tmp_002-11,14,gcc,clang.cpp:10:16: warning: ‘std::ostream& foo::operator<<(std::ostream&, const foo::bar&)’ has not been declared within foo
std::ostream & foo::operator<< (std::ostream & o, foo::bar const &)
^~~
tmp_002-11,14,gcc,clang.cpp:7:29: note: only here as a friend
{ friend std::ostream & operator<< (std::ostream &, bar const &); };
^~~~~~~~
我知道我可以如下定义运算符
namespace foo
{
std::ostream & operator<< (std::ostream & o, bar const &)
{ return o; }
}
但是...我的初始代码有什么问题?
nm的答案是正确的,虽然我需要更多的挖掘来解决它的原因,所以这里有一些我遵循的链接:
CppCoreGuidelines解释说“非成员运算符应该是朋友或者在与其操作数相同的名称空间中定义” 。 这里有一个更详细的解释为什么相同的命名空间 。
也许这个来自GCC邮件列表的这条消息提供了更多的洞察力:看起来好像海湾合作委员会的人决定在2016年的某个时候更严格地处理这个问题。
这里的关键是命名空间。 如果它在命名空间foo中而不是在外部定义了运算符<<,那么你的代码就可以了,就像这样:
namespace foo
{
struct bar
{
friend std::ostream & operator<< (std::ostream &, bar const &);
};
// Implementation
std::ostream & operator<< (std::ostream & o, foo::bar const &)
{ return o; }
}
请注意,如果您将实现直接与朋友定义一起使用,这会变得更简单, 如此SO回答类似问题所示 。
对于一个非常相似的问题 ,这是另一个非常精细的答案。 当我试图修复同样的问题时,它帮助了我(gcc 7给了我这个用于编译很好旧代版本的代码的警告)。
考虑一下这个简单的程序:
namespace xxx {
struct foo {
friend void bar();
};
}
int main() {
xxx::bar();
}
您将收到编译错误(也有clang),因为bar
未在命名空间xxx
声明。
现在考虑一下:
namespace xxx {}
void xxx::bar() {}
这也会因为相同的原因而失败, bar
未在命名空间xxx
声明。
现在当你把两者结合起来时,没有理由说这个组合突然变得合法了。 bar
仍未在命名空间xxx
声明。 然而clang允许它。 此行为不一致且令人困惑,最好将其描述为错误。
我使用的是visual studio所以我不确定它是否会为你解决问题,但我发现错误的唯一一件事是你的运营商声明。 基本上它始终是
const type_name variable_id &;
Ampersand总是排在最后,const排在第一位,对我来说它现在正在运行。
您应该更改您的运营商声明并:
friend std::ostream & operator<< (std::ostream &,const bar&);
在你的定义中更低:
std::ostream & foo::operator<< (std::ostream & o, const foo::bar &)
嗯,我遇到了同样的问题。 但是我找到了一种解决方法:在命名空间范围内添加另一个函数声明。
像这样:
namespace foo {
class A {
public:
friend std::ifstream &operator >> (std::ifstream &in, A &a);
};
std::ifstream &operator >> (std::ifstream &in, A &a);
}
std::ifstream &foo::operator >> (std::ifstream &in, A &a) {
[...]
return in;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.