std::to_string尽管使用了using指令,编译器仍然看不到该函数.这是为什么?
#include <string>
namespace MySpace
{
using namespace std;
struct X
{
int n;
};
string to_string(X x)
{
return to_string(x.n);//Error here
}
}
Run Code Online (Sandbox Code Playgroud)
如果我把东西移出MySpace全局命名空间,或者我明确地添加using std::to_string;声明,那么一切正常MySpace.
这是因为[namespace.udir]:
在非限定名称查找(6.4.1)期间,名称看起来好像是在最近的封闭命名空间中声明的,其中包含using-directive和指定的命名空间.
因此using namespace std;,出于非限定名称的目的,查找实际上将名称带入全局命名空间,而不是MySpace.在声明MySpace隐藏声明从namespace std介绍了这种方式.
如果将所有内容移动到全局命名空间中,它就会开始工作,因为您自己的to_string并且std::to_string现在出现在同一名称空间中,就非限定查询而言.
原因是真正的晦涩,并且与using指令和重载解析的工作方式有关.
首先,让我们看一下该using指令.当你在另一个命名空间中注入命名空间时,它通过实际注入命名空间来工作
最近的封闭命名空间,包含using-directive和namespace [正在使用].(https://en.cppreference.com/w/cpp/language/namespace#Using-directives).
在你的情况下,这样的命名空间将是全局命名空间,它是唯一包含std和的命名空间My Space.它的作用是在命名空间中定义的名称std就像在全局命名空间中定义一样.
我们现在来看看重载决策.当通过名称查找函数时,首先在本地名称空间中搜索名称,如果没有找到,则在周围的名称空间中继续搜索,然后向上一级... - 直到找到名称,或者我们到达全局命名空间 一旦找到至少一个名称,搜索就会停在那里,并使用重载规则从名称集中选择一个限定的重载.在您的情况下,此搜索立即产生一个名称 - to_string- 被拒绝,因为它不接受int参数(它只接受X).
另一方面,当您不使用时MySpace,名称from std也会放在全局名称空间中,但您自己的to_string名称现在存在于全局名称空间中.因此,to_string在全局命名空间中找到多个版本,包括您的版本,并且to_string(int)根据参数类型选择正确的版本.