了解命名空间的合格名称查找

时间:2015-02-11 11:24:12

标签: c++ c++11 namespaces language-lawyer

我想了解名称空间限定名称查找。我正在尝试利用以下

  

3.4.3.2.2:对于命名空间X和名称m,命名空间限定的查找集S(X,m)定义如下:设S'(X,m)是所有的集合   X中的m的声明和X的内联命名空间集(7.3.1)。如果   S'(X,m)不为空,S(X,m)为S'(X,m);否则,S(X,m)就是   对于由using-directives指定的所有名称空间N_i的S(N_i,m)的并集   在X及其内联命名空间集中。

为标准命名空间中不存在的名称提供回退机制。以下程序举例说明了我想要实现的目标

#include <type_traits>
namespace foo
{
    template<class Ty>
    struct remove_extent
        {
        typedef Ty type;
        };
}
namespace fallback
{
    using namespace std;
}
namespace fallback
{
    using namespace foo;
}
template<typename Ty>
struct Bar
{
    typename fallback::remove_extent<Ty>::type var;
};
int main()
{
   Bar<int[]> var;
}

第一次申报

namespace fallback
{
    using namespace std;
}

S'(fallback, remove_extent)是一个空集,因此S(fallback, remove_extent)S(std, remove_extent).的联合

对于第二个声明

namespace fallback
{
    using namespace foo;
}

S'(fallback, remove_extent)非空,因此S(fallback, remove_extent) = S'(fallback, remove_extent) = S(std, remove_extent)

但我的编译器认为不然并抱怨

1>source.cpp(21): error C2872: 'remove_extent' : ambiguous symbol
1>          could be 'source.cpp(6) : foo::remove_extent'
1>          or       'c:\program files (x86)\microsoft visual studio 11.0\vc\include\type_traits(331) : std::remove_extent'

显然,我的理解是错误的。为什么编译器包含来自foo的名称remove_extent

1 个答案:

答案 0 :(得分:4)

  

对于第二个声明...... S'(fallback, remove_extent)非空

不,它不是:

namespace fallback
{
    using namespace std;
}

在此之后,S'(fallback, remove_extent)为空,因此SS(std, remove_extent)

namespace fallback
{
    using namespace foo;
}

在此之后,S'(fallback, remove_extent) 仍然为空(即 {{ 1}}),因此remove_extent现在是fallbackS的联合。

S(std, remove_extent)

当我们到达这一点时,S(foo, remove_extent)中有两个名为template<typename Ty> struct Bar { typename fallback::remove_extent<Ty>::type var; }; 的实体(一个来自remove_extent,一个来自fallback,两者都没有直接在{{1}中声明因此编译器会正确地告诉您名称不明确。