编译器正在尝试从 int 初始化枚举类,而它没有



我有一个类型的枚举类,并且需要一个"to_string"函数来输出类型名称,所以我在自己的名称空间中编写了它。问题是,该命名空间中的其他函数试图调用to_string,例如,int(实际上只是int,不打算成为enum的一部分)正在查找自定义to_string并给出关于枚举初始化无效的错误。

我知道我可以显式地调用std::to_string而不是to_string,但我认为有更好的方法。我做错了什么?

下面是示例代码:

#include <iostream>
#include <string>
namespace other {
    enum class Type {
        Type1,
        Type2
    };
    std::string to_string(const Type& type) {
        switch(type) {
            case Type::Type1:
                return "Type1";
                break;
            case Type::Type2:
                return "Type2";
                break;
            default:
            {}
        }
        return "Unknown";
    }
    void run() {
        using namespace std;
        cout << string("Type: ") + to_string(Type::Type1) << endl;
        cout << string("int: " )  + to_string(42) << endl;  // this one generates compile-time errors
    }
}
int main() {
    other::run();
    using namespace std;
    cout << string("int: " )  + to_string(42) << endl;  // This one is ok
    return 0;
}

您需要显式指定要将什么函数引入"重载集" (参见wandbox示例):

void run() {
    using namespace std;
    using std::to_string;
    cout << string("Type: ") + to_string(Type::Type1) << endl;
    cout << string("int: " )  + to_string(42) << endl;  
}

原因是ADL忽略了using指令。请参阅 3.4.2 [basic.lookup.argdep] :

当考虑关联的命名空间时,查找与将关联的命名空间用作限定符(3.4.3.2)时执行的查找相同,除了:-关联命名空间中的任何using指令都会被忽略。

在这个问题中有更详细的信息

这是一个棘手的情况,涉及到名称空间的一些微妙规则。让我们考虑一个更简单的例子:

namespace b {
  void f(int) { }
}
namespace a {
  using namespace b;
  void f(char) { }
  void g()
  {
    f(5); // calls f(char)
  }
}

这里的问题是,即使我们有using namespace b, b中的声明也被视为在公共命名空间(全局)中声明的,用于查找:

(c++ 14 7.3.4/2)

using-directive指定指定的命名空间中的名字可以在指定的作用域中使用Using-directive出现在Using-directive之后。在非限定名称查找(3.4.1)期间,会出现这些名称就好像它们是在最近的封闭命名空间中声明的,该命名空间包含using指令和指定名称空间。[注:在本文中,"contains"意为"直接或间接包含"。- - -结束注意]

因此,出于查找的目的,名称空间b中的名称被视为全局名称空间中的名称。这意味着命名空间a中的f(char)将隐藏命名空间b中的f(int):

(c++ 14 3.3.10/4)

在查找由名称空间名称限定的名称期间,否则将进行的声明在using指令中可见的可以被同名的声明隐藏使用指示;见(3.4.3.2)。

在您的示例中,调用other::run()中的to_string(42)将找到other::to_string,因为std::to_string(int)是隐藏的。

最新更新