【问题标题】:Why is typename _not_ needed here in Visual Studio 2008/2010?为什么在 Visual Studio 2008/2010 中此处不需要类型名?
【发布时间】:2011-04-15 23:18:32
【问题描述】:

this question中,asker有如下功能:

template<typename ITER>
bool nextPermutation(ITER start, ITER end)
{
    return nextPermutation(start, end, std::iterator_traits<ITER>::iterator_category());
}

为什么在std::iterator_traits 之前不需要typename?我认为模板的嵌套类型需要它,如果模板依赖于模板参数本身? GCC 似乎支持我的想法,因为它不能在4.3.44.5.1 下编译,需要typename。即便如此,它在 Visual Studio 2008 和 2010 下仍然可以正常编译。
这只是我不知道的另一个 Visual Studio 扩展/错误吗?
或者实际上可以推断出iterator_category 是一个类型还是一个函数,因为它后面跟着一对括号()? (请参阅@DeadGM 的消息starting here。)那么这实际上可能是 GCC 中的一个错误吗?

【问题讨论】:

  • 除了您列出的选项(构造函数和函数)之外,iterator_category 可以是定义 operator() 的类型的静态成员变量。
  • @Sjoerd:或者一个函数指针。

标签: c++ visual-studio typename


【解决方案1】:

众所周知,Visual C++ 不(完全)支持两阶段查找,这就是为什么首先需要typename 的根本原因。如果编译器不完全支持这一点,它可能不会在模板实例化之前完全解析模板,到那时它“知道”std::iterator_traits&lt;ITER&gt;::iterator_category 是一种类型。显然,这种缺陷延伸到了 VC10。

谈到typename,我相信 GCC 胜过 VC。

【讨论】:

  • 完美完整的答案,但我会接受@Johannes 的答案,因为它解释了更多关于后期解析的事情。 +1虽然。 :)
【解决方案2】:

MSVC 不实现后期解析方案吗?在这样的方案中,编译器不依赖于typename。它只是将所有标记存储在模板定义的大括号之间,当模板被实例化时,它会解析这些标记。因为它知道什么是类型,什么不是类型,所以它可以在没有typename 的情况下工作。

但是,如果编译器在您实例化模板时没有诊断出缺少的typename,那么它就是不合格的。

或者是否真的可以推断出 iterator_category 是一个类型或一个函数,因为它后面跟着一对括号 ()?

重要的是名称是否依赖和限定。模板是否可以推断出名称始终是类型并不重要。不过,丢失typenames 可能对错误消息的质量很重要。

FWIW,不,不可能在语言层面上推断出任何关于 iterator_category 的信息。

【讨论】:

  • 请注意,所需的诊断允许只是一个警告。所以只要编译器发出至少一个警告,就可以“编译得很好”。其次,默认情况下可以关闭该警告——我知道的所有编译器都需要一个标志或选项,以便尽可能地遵循 C++ 标准:升级编译器时,大多数客户不希望出现新的警告/错误对于他们的旧代码,因此向后兼容性迫使编译器编写者将新错误隐藏在附加选项后面。
  • @Sjoerd:标准总是只提到“诊断”。这可能是错误或警告,都可以。
  • @sbi 我相信你和 Johannes 都知道,但这不是常识。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-28
相关资源
最近更新 更多