簡體   English   中英

警告定義在命名空間內聲明的友元運算符

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM