max*_*x66 7 c++ namespaces g++ operator-overloading friend
有人可以向我解释来自 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;
}
Run Code Online (Sandbox Code Playgroud)
我得到(来自 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 &); };
^~~~~~~~
Run Code Online (Sandbox Code Playgroud)
我知道我可以如下定义运算符
namespace foo
{
std::ostream & operator<< (std::ostream & o, bar const &)
{ return o; }
}
Run Code Online (Sandbox Code Playgroud)
但是...我的初始代码有什么问题?
考虑这个简单的程序:
namespace xxx {
struct foo {
friend void bar();
};
}
int main() {
xxx::bar();
}
Run Code Online (Sandbox Code Playgroud)
你会得到一个编译错误(也有 clang),因为bar没有在命名空间中声明xxx。
现在考虑一下:
namespace xxx {}
void xxx::bar() {}
Run Code Online (Sandbox Code Playgroud)
这也会由于同样的原因而失败,bar即未在名称空间中声明xxx。
现在,当您将两者结合起来时,没有理由认为这种组合会突然变得合法。bar仍未在命名空间中声明xxx。然而 clang 允许这样做。这种行为不一致且令人困惑,最好将其描述为错误。
nm的答案是正确的,虽然我需要更多的挖掘才能知道原因,所以这里有一些我遵循的链接:
CppCoreGuidelines 解释说“非成员运算符应该是朋友或在与其操作数相同的命名空间中定义”。这里更详细地解释了为什么使用相同的命名空间。
也许这个来自 GCC 邮件列表的消息提供了更多的洞察力:看起来 GCC 人决定在 2016 年的某个时候更严格地处理这个问题。
这里的关键是命名空间。如果您的代码在命名空间foo 内而不是外部定义了operator<< ,那么您的代码就可以了,如下所示:
namespace foo
{
struct bar
{
friend std::ostream & operator<< (std::ostream &, bar const &);
};
// Implementation
std::ostream & operator<< (std::ostream & o, foo::bar const &)
{ return o; }
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果您直接将实现与朋友定义放在一起,这会变得更简单,如this SO answer to a similar question所示。
这是对一个非常相似的问题的另一个非常详细的 SO 答案。当我试图解决同样的问题时,它对我有所帮助(gcc 7 给了我这个警告,因为代码可以用更旧的版本编译得很好)。
| 归档时间: |
|
| 查看次数: |
2280 次 |
| 最近记录: |