尽管使用了指令,编译器仍看不到函数std::to_string
。为什么会这样?
#include <string>
namespace MySpace
{
using namespace std;
struct X
{
int n;
};
string to_string(X x)
{
return to_string(x.n);//Error here
}
}
如果将内容从MySpace
中移出到全局命名空间,或者将using std::to_string;
声明显式添加到MySpace
中,则一切正常。
答案 0 :(得分:6)
是由于以下 [namespace.udir] :
在不合格的名称查找(6.4.1)中,名称出现 就像它们是在最近的封闭命名空间中声明的一样,该命名空间同时包含using-directive和 提名的名称空间。
因此using namespace std;
实际上是为了进行不合格名称查找而将名称引入全局命名空间,而不是引入MySpace
。 MySpace
中的声明隐藏了以这种方式引入的namespace std
中的声明。
如果将所有内容移至全局名称空间,则它开始工作,因为就不合格查找而言,您自己的to_string
和std::to_string
现在出现在同一名称空间中。
答案 1 :(得分:5)
原因确实是不可思议的,并且与using
指令和重载解析的工作方式有关。
首先,让我们看一下using
指令。当您将名称空间注入另一个名称空间时,它实际上是通过将名称空间注入
最近的封闭名称空间,其中包含 using-directive和namespace(正在使用)。 (https://en.cppreference.com/w/cpp/language/namespace#Using-directives)。
在您的情况下,这样的名称空间将是全局名称空间,是否它将是唯一包含std
和My Space
的名称空间。这样做的结果是,在命名空间std
中定义的名称的行为就像在全局命名空间中定义的一样。
现在让我们看一下重载解决方案。当通过名称查找函数时,首先在本地名称空间中搜索名称,如果找不到,则继续在周围的名称空间中搜索,然后向上一级...-直到找到名称,或者我们到达全局名称空间。一旦找到至少一个名称,搜索就会在此处停止,然后使用重载规则从名称集中选择一个合格的重载。在您的情况下,此搜索会立即产生一个名称-to_string
-被拒绝,因为它不接受int
自变量(仅接受X
)。
另一方面,当您不使用MySpace
时,来自std
的名称也被放入全局命名空间中,但是您自己的to_string
现在存在于全局命名空间中。结果,在全局名称空间(包括您的名称空间)中找到了多个to_string
版本,然后根据参数类型选择了正确的一个to_string(int)
。
答案 2 :(得分:2)
代码的问题是由于用法错误,您未在std::to_string
的定义内调用MySpace::to_string
。因此,它也可以在名称空间MySpace
中正常工作,只是阴影to_string
函数在std
名称空间中起作用。
以下代码可以正常编译:
namespace MySpace
{
using namespace std;
struct X
{
int n;
};
string to_string(X x)
{
return std::to_string(x.n); // No error anymore here
}
}
答案 3 :(得分:-1)
最好的方法是将特定功能导入名称空间。
#include <string>
#include <iostream>
namespace MySpace
{
using std::to_string;
struct X
{
int n;
};
std::string to_string(const X &x)
{
return to_string(x.n);
}
}