模板实例化的范围解析

时间:2011-11-22 12:39:44

标签: c++ templates visual-c++ name-lookup

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

namespace Parent
{
  class A {};

  namespace Nested
  {
    class A {};
  }

  template <typename T>
  class B
  {
    A myA;
  };
}

我希望成员Parent::B::myA应明确地解析为Parent::A类型。但是,在我的项目的其他地方,我有这个:

namespace Parent
{
  using namespace Nested;

  void foo()
  {
    B<int> myB;
  }
}

无法在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 ]

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

1 个答案:

答案 0 :(得分:6)

在所有版本的MSVC中,这是一个长期存在的错误。

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

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

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

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

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