MSVC 是否错误地处理依赖名称中的模板关键字?

Fur*_*ish 5 c++ templates language-lawyer

知道我们必须在哪里以及为什么要放置templateandtypename关键字后,我惊讶地发现 MSVC接受以下代码:

struct foo {
    using bar = int;
};

template <typename T>
void quux() {
    T::template bar b;
}

int main() {
    quux<foo>();
}
Run Code Online (Sandbox Code Playgroud)

根据我的理解, 的用法T::template bar b;是不正确的。声明的正确方法b是使用typename,如下所示:(typename T::bar b;而不是T::template bar b;)。template将意味着这bar是一个模板,但事实并非如此。

它是 MSVC 中的错误导致它接受不正确的代码,还是标准允许它并且 Clang 和 GCC 都没有以这种方式实现它(因此需要正确使用typename此处)?

MSa*_*ers 1

MSVC 有一个长期存在的错误 - 当我询问您链接的模板类型名称问题时,它已经是一个老错误了。简而言之,自 1998 年以来,C++ 要求在模板中进行两阶段名称查找。在第一阶段,当编译模板本身时,仅查找不依赖的名称,因为尚不知道实际的模板参数。在第二阶段,查找依赖名称(有关详细信息,请参阅链接的问题)。

但MSVC不会这样做,而是在实例化模板时进行所有查找。在您的情况下,这意味着所有查找都在 MSVC 编译时完成quux<foo>,而在编译时则不执行任何操作quux<T>。由于它不执行第一阶段,因此它不需要typename依赖名称。MSVC 已经了解quux::b.

看来 MSVC 走得更远一些。它不仅忽略了正确的typename,而且还忽略了template本示例中错误使用的 as 。当忽略一些事情时,这并不完全令人惊讶。

  • 它已在 VS2019 中得到修复 [Visual Studio 2019 中的 C++ 一致性改进、行为更改和错误修复](https://learn.microsoft.com/en-us/cpp/overview/cpp-conformance-improvements?view=msvc- 160)。您需要 `/Zc:twoPhase-` 来实现旧行为 (3认同)