【问题标题】:Scope resolution for template instantiation模板实例化的范围解析
【发布时间】:2012-01-03 20:19:20
【问题描述】:

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

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 的一个错误,还是我真的应该担心我的模板可能被实例化的范围?

【问题讨论】:

  • 这很有趣。显然,命名空间 usings 在实例化模板时按词法工作。太令人惊讶了
  • FWIW:g++ 4.5.3 同意这不应该是一个问题
  • @sehe:这不是问题(标准方面),但 MSVC 在模板方面不符合标准...(即使在最新版本中也不符合)

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


【解决方案1】:

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

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

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

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

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

如果可以,请放弃 MSVC。如果你不能......祝你好运。

【讨论】:

  • 太棒了。很好的解释
  • @sehe:老实说,我觉得很遗憾,这么大的产品没有以更高的合规性为目标。我想这源于 VC++ 在 Windows 市场上的压倒性地位:他们不想做得更好,因为他们没有共识,因此没有动力。
  • 没有同意 -> 没有竞争?哦,我同意。另见VC++ Team Blog on C++11
  • @MatthieuM。谢谢 - 很高兴知道发生了什么,但很遗憾知道即使迁移到更新的 MSVC 也无济于事! (不幸的是,我看不到我的组织离开 MSVC 环境的前景。)您能否建议我可以链接到我的代码的未来读者的参考?否则,我将在此处使用您的答案的永久链接;-)
  • @sehe:谢谢你的链接,我没有关注最新的动作,它确实很有启发性。太糟糕了,因为 Herb Sutter 在 MS 和 C++ 委员会都处于如此高的位置,以至于 C++ 最终会成为第二个区域公民:(
猜你喜欢
  • 1970-01-01
  • 2015-10-14
  • 1970-01-01
  • 2019-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-25
  • 1970-01-01
相关资源
最近更新 更多