模板实例化的范围解析

atk*_*ins 6 c++ templates visual-c++ name-lookup

我有以下一组类(我的实际情况的最小复制):

namespace Parent
{
  class A {};

  namespace Nested
  {
    class A {};
  }

  template <typename T>
  class B
  {
    A myA;
  };
}
Run Code Online (Sandbox Code Playgroud)

我希望该成员Parent::B::myA应该毫不含糊地解决为类型Parent::A.但是,在我的项目的其他地方我有这个:

namespace Parent
{
  using namespace Nested;

  void foo()
  {
    B<int> myB;
  }
}
Run Code Online (Sandbox Code Playgroud)

无法在MSVC 2003下编译:

error C2872: 'A' : ambiguous symbol
        could be 'Test.cpp(5) : Parent::A'
        or       'Test.cpp(9) : Parent::Nested::A'
        Test.cpp(26) : see reference to class template instantiation 'Parent::B<T>' being compiled
        with [ T=int ]
Run Code Online (Sandbox Code Playgroud)

如果我明确声明B::myA,即代码将编译Parent::A myA;.但是,代码在gcc-4.3.4编译.这只是MSVC 2003的一个错误,还是我真的不得不担心我的模板可以实例化的范围?

Mat*_* M. 6

这是所有版本的MSVC中的长期错误.

问题与MSVC中模板中名称查找的错误实现有关.

基本上,MSVC将等到实例化点执行名称查找,而标准明确指出正确的行为是:

  • 对非依赖符号立即执行名称查找(在声明点)
  • 在实例化时为依赖符号执行名称查找

这种行为允许MSVC在使用typenameor 方面松懈template,因为它可以完全推导符号性质(区分常规变量与函数或类型),但是当一个目标与其他编译器兼容时,这是一场噩梦.

如果可以,抛弃MSVC.如果你不能......祝你好运.

  • @sehe:说实话,我觉得很难过这么大的产品不会追求更多的合规性.我想这源于VC++在Windows市场上的压倒性地位:他们并不关心做得更好,因为他们没有同意,因此没有激励. (2认同)