[英]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.