C++ 编译器正在尝试从int初始化枚举类,但它应该在';T

C++ 编译器正在尝试从int初始化枚举类,但它应该在';T,c++,enums,C++,Enums,我有一个类型的枚举类,需要一个“to_string”函数来输出类型名,所以我在自己的命名空间中编写了这个函数。问题是,该命名空间中的其他函数试图调用上的_字符串,例如int(实际上只是一个int,不打算成为枚举的一部分)正在查找自定义的to_字符串,并给出有关枚举无效初始化的错误 我知道我可以显式地调用std::to_string而不是to_string,但我认为有更好的方法。我做错了什么 示例代码是: #include <iostream> #include <string&

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

我知道我可以显式地调用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;
}
#包括
#包括
名称空间其他{
枚举类类型{
类型1,
类型2
};
std::字符串到_字符串(常量类型和类型){
开关(类型){
案例类型::类型1:
返回“Type1”;
打破
案例类型::类型2:
返回“Type2”;
打破
违约:
{}
}
返回“未知”;
}
无效运行(){
使用名称空间std;

cout您需要明确指定要将什么函数引入“重载集”():

void run(){
使用名称空间std;
使用std::to_字符串;

CUT

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

namespace b {
  void f(int) { }
}

namespace a {
  using namespace b;

  void f(char) { }

  void g()
  {
    f(5); // calls f(char)
  }
}
这里的问题是,尽管我们使用了
名称空间b
,但b中的声明被视为是在公共名称空间(全局)中声明的,以便查找:

(C++14.7.3.4/2)

using指令指定指定命名空间中的名称可以在 using指令出现在using指令之后。在非限定名称查找(3.4.1)过程中,名称将出现 就好像它们是在最近的封闭名称空间中声明的,该名称空间包含using指令和 指定名称空间[注意:在此上下文中,“包含”表示“直接或间接包含”。-结束 注]

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

(C++143.3.10/4)

在查找由命名空间名称限定的名称的过程中,可能会进行的声明 using指令可见的可以通过包含 使用指令;参见(3.4.3.2)


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

为什么需要这样做?编译器不应该检测到从int到Type的转换无效,然后继续寻找另一个有效的签名吗(并以std::to_string结尾)?引入
std::to_string
显式地使此方法在名称查找中更匹配。如果没有此方法,您将支付(粗略地说)对于命名空间层次结构中的每个步骤。通过导入,可以免费使用。很抱歉没有提供解释,我正试图找到一个好的源代码/标准部分来引用。因此,函数位于“lower”如果名称相同,名称空间将对更高级别的函数进行阴影处理?即使签名不同?编译器在尝试匹配签名时没有发现错误,然后继续进一步查找有效匹配,这有什么实际原因吗?@ryan0270:是的,在scop中进行重载工作被认为太混乱了es.这里更详细:只是我对事物的看法…如果你可以更具体一些,那么就这样做。例如,在你的
run()
中,我会键入
other::to_string
std::to_string
,这样编辑它的下一个可怜的家伙就知道我的意图。好问题,我以前从未考虑过命名空间隐藏/重载。
namespace b {
  void f(int) { }
}

namespace a {
  using namespace b;

  void f(char) { }

  void g()
  {
    f(5); // calls f(char)
  }
}