简体   繁体   English

警告定义在命名空间内声明的友元运算符

[英]warning defining friend operator declared inside a namespace

Someone can explain me a warning from g++ ?有人可以向我解释来自 g++ 的警告吗?

Given the following code鉴于以下代码

#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;
 }

I get (from g++ (6.3.0) but not from clang++ (3.8.1) and not (thanks Robert.M) from Visual Studio (2017 community)) this warning我得到(来自 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 &); };
                             ^~~~~~~~

I know that I can define the operator as follows我知道我可以如下定义运算符

namespace foo
 {
   std::ostream & operator<< (std::ostream & o, bar const &)
    { return o; }
 }

but... what's wrong with my initial code ?但是...我的初始代码有什么问题?

The answer of nm is right, although I needed a bit more digging to get it why, so here are some links that I followed: nm的答案是正确的,虽然我需要更多的挖掘来解决它的原因,所以这里有一些我遵循的链接:

The CppCoreGuidelines explain that "Nonmember operators should be either friends or defined in the same namespace as their operands" . CppCoreGuidelines解释说“非成员运算符应该是朋友或者在与其操作数相同的名称空间中定义” Here's a more detailed explanation of why the same namespace . 这里有一个更详细的解释为什么相同的命名空间
Maybe this this message from the GCC mailing list provides even more insight: it looks as if the GCC people decided to handle this issue more strictly some time im 2016. 也许这个来自GCC邮件列表的条消息提供了更多的洞察力:看起来好像海湾合作委员会的人决定在2016年的某个时候更严格地处理这个问题。

The key here is the namespace. 这里的关键是命名空间。 Your code would be OK if it defined the operator<< within the namespace foo instead of outside, like this: 如果它在命名空间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; }
}

Note that this gets simpler, if you put the implementation directly with the friend definition, as shown in this SO answer to a similar question . 请注意,如果您将实现直接与朋友定义一起使用,这会变得更简单, 如此SO回答类似问题所示

Here is another, quite elaborate SO answer to a very similar question . 对于一个非常相似的问题 ,这是另一个非常精细的答案。 It helped me when I tried to fix the same problem (gcc 7 gave me this waring for code that compiled fine with much older versions). 当我试图修复同样的问题时,它帮助了我(gcc 7给了我这个用于编译很好旧代版本的代码的警告)。

Consider this simpme program: 考虑一下这个简单的程序:

namespace xxx { 
    struct foo {
       friend void bar();
    };
}

int main() {
    xxx::bar();
}

You will get a compilation error (with clang too) because bar is not declared in namespace xxx . 您将收到编译错误(也有clang),因为bar未在命名空间xxx声明。

Now consider this: 现在考虑一下:

namespace xxx {}
void xxx::bar() {}

This will also fail for the same ecact reason, bar is not declared in namespace xxx . 这也会因为相同的原因而失败, bar未在命名空间xxx声明。

Now when you combine the two, there's no reason why the combination should suddenly become legal. 现在当你把两者结合起来时,没有理由说这个组合突然变得合法了。 bar is still not declared in namespace xxx . bar仍未在命名空间xxx声明。 Yet clang permits it. 然而clang允许它。 This behaviour is inconsistent and confusing, and is best described as a bug. 此行为不一致且令人困惑,最好将其描述为错误。

I was using visual studio so I am not sure if it will solve a problem for you but the only thing I found wrong was a declaration of your operator. 我使用的是visual studio所以我不确定它是否会为你解决问题,但我发现错误的唯一一件事是你的运营商声明。 Basicly it is always 基本上它始终是

        const type_name variable_id &;

Ampersand always comes last and const comes first, for me it is running now. Ampersand总是排在最后,const排在第一位,对我来说它现在正在运行。

You should change your operator declaration and to: 您应该更改您的运营商声明并:

        friend std::ostream & operator<< (std::ostream &,const bar&);

And lower in your definition: 在你的定义中更低:

std::ostream & foo::operator<< (std::ostream & o,  const foo::bar &)

Well, I met the same problem.嗯,我遇到了同样的问题。 However I found a way to fix it: add another declaration of the function, within the namespace scope.但是我找到了一种解决方法:在命名空间范围内添加另一个函数声明。

Just like this:像这样:

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