在名称空间中使用指令和函数重载

时间:2018-08-20 17:52:10

标签: c++

尽管使用了指令,编译器仍看不到函数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中,则一切正常。

4 个答案:

答案 0 :(得分:6)

是由于以下 [namespace.udir]

  

在不合格的名称查找(6.4.1)中,名称出现   就像它们是在最近的封闭命名空间中声明的一样,该命名空间同时包含using-directive和   提名的名称空间。

因此using namespace std;实际上是为了进行不合格名称查找而将名称引入全局命名空间,而不是引入MySpaceMySpace中的声明隐藏了以这种方式引入的namespace std中的声明。

如果将所有内容移至全局名称空间,则它开始工作,因为就不合格查找而言,您自己的to_stringstd::to_string现在出现在同一名称空间中。

答案 1 :(得分:5)

原因确实是不可思议的,并且与using指令和重载解析的工作方式有关。

首先,让我们看一下using指令。当您将名称空间注入另一个名称空间时,它实际上是通过将名称空间注入

  

最近的封闭名称空间,其中包含   using-directive和namespace(正在使用)。 (https://en.cppreference.com/w/cpp/language/namespace#Using-directives)。

在您的情况下,这样的名称空间将是全局名称空间,是否它将是唯一包含stdMy 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);
    }
}

https://wandbox.org/permlink/BD520ZCACv9hwF4q