我有一个enum类的类型,想要一个" to_string"用于输出类型名称的函数,所以我在我自己的命名空间中编写了它。问题是,该命名空间中的其他函数试图调用to_string,例如,一个int(实际上只是一个int,不打算成为枚举的一部分)是找到自定义的to_string并给出有关枚举无效初始化的错误。
我知道我可以显式调用std :: to_string而不是to_string,但我认为这是更好的方法。我做错了什么?
Here是示例代码:
#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;
}
答案 0 :(得分:4)
您需要明确指定要将哪些功能引入&#34;重载集&#34; (see wandbox example):
<cassandra-driver.version>3.0.3</cassandra-driver.version>
原因是ADL忽略了使用指令。请参阅 3.4.2 [basic.lookup.argdep] :
在考虑关联的命名空间时,查找与关联命名空间用作限定符时执行的查找相同(3.4.3.2),但以下情况除外: - 忽略关联命名空间中的任何using-directive。
更详细的信息in this question。
答案 1 :(得分:3)
这是一个棘手的情况,涉及名称空间的一些细微规则。让我们考虑一个更简单的例子:
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-directive和 提名命名空间。 [注意:在此上下文中,“包含”表示“直接或间接包含”。 - 结束 注意]
因此,出于查找的目的,名称空间b中的名称被视为它们在全局名称空间中。这意味着命名空间a中的f(char)
将在命名空间b中隐藏f(int)
:
(C ++ 14 3.3.10 / 4)
在查找由命名空间名称限定的名称期间,否则将进行声明 using-directive 可以在包含的名称空间中使用相同名称的声明隐藏 使用指令;见(3.4.3.2)。
在您的示例中,to_string(42)
中对other::run()
的调用会找到other::to_string
,因为隐藏了std::to_string(int)
。