c++ - 两个运算符(operator)的一些奇怪冲突<<

标签 c++ c++17

为什么以下代码无法编译?

#include <iostream>

namespace X
{
    inline std::wostream & operator<<(std::wostream & stm, int a)
    {
        stm << L"int";
        return stm;
    }
}

namespace Y
{
    class A
    {
    };
}

inline std::wostream & operator<<(std::wostream & stream, const Y::A & msg)
{
    stream << L"A";
    return stream;
}

namespace X
{
    void f()
    {
        Y::A a;
        std::wcout << a;
    }
}

为什么要删除命名空间X中的operator <<,使代码得以编译?尝试将其注释掉,例如:
namespace X
{
    //inline std::wostream & operator<<(std::wostream & stm, int a)
    //{
    //    stm << L"int";
    //    return stm;
    //}
}

这些运算符之间的依赖性是什么?

参见live example

编辑1:

我唯一的猜测是,在使用该 namespace 的同一个命名空间中声明的运算符以某种方式将其隐藏在其他命名空间中,但是我之前从未听说过...

编辑2:

实际上,在我的项目中,第二个运算符位于 namespace Z中(但不是全局名称):
...

namespace Z
{
    inline std::wostream & operator << (std::wostream & stream, const Y::A & msg)
    {
        stream << L"A";
        return stream;
    }
}

namespace X
{
    void f()
    {
        using namespace Z;
        Y::A a;
        std::wcout << a;
    }
}

导致相同的编译器错误。

最佳答案

实际上,此行为在C++中是可以预期的,以避免由不同 namespace 中的不同重载引起的意外行为。

这称为名称隐藏
您可以在此处阅读有关该主题的非常好的答案:https://stackoverflow.com/a/1629074/182676

因此,不同 namespace 中的重载将相互隐藏。

您可以通过使用using使编译器可见正确的重载来解决此问题:

Y::A a;
using Z::operator<<;
std::wcout << a;

关于c++ - 两个运算符(operator)的一些奇怪冲突<<,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60157260/

相关文章:

c++ - C++ 中的模函数,其行为类似于 matlab 中的模

c++ - 为什么用execute::par对 vector 进行排序要比正常排序(gcc 10.1.0)花费更长的时间?

c++ - 为什么基于范围的 for 循环中的结构化绑定(bind)只是拷贝而不是引用?

c++ - 将 std::bind 与 std::visit 一起使用

c++ - 为什么模板实例化中不允许使用 lambda?

c++ - 尝试实现堆栈时 C++ 中的 undefined reference

c++ - 使用 boost Spirit 为变量分配默认值

c++ - std::get_temporary_buffer 返回原始指针而不是智能指针

c++ - 有没有办法创建一个以成员函数或成员作为参数的函数?

c++ - 在 switch 语句中分配 lambda