为什么我不需要在 C++20 中的依赖类型之前指定“typename”?

Jak*_*idt 70 c++ templates typename language-lawyer c++20

这段代码在 C++20(使用 gcc 10.1)中编译,typename在依赖类型之前没有使用关键字std::vector<T>::iterator。为什么要编译?

#include <vector>

template<typename T>
std::vector<T>::iterator // Why does this not require "typename" before it?
f() { return {}; }

int main() {
    auto fptr = &f<int>;
}
Run Code Online (Sandbox Code Playgroud)

代码游乐场

Bar*_*rry 65

C++20 的新特性之一是Down withtypename .

在 C++17 中,您必须typename在几乎所有依赖上下文中提供关键字以消除类型与值的歧义。但是在 C++20 中,这个规则放宽了很多。在需要类型的所有上下文中,typename关键字不再是必需的。

一个这样的上下文是类范围内函数的返回类型,如您的示例所示。其他包括成员声明中的类型、using 声明右侧的类型、lambda 的参数声明、您传递给的类型static_cast等。请参阅论文以获取完整列表。


几乎所有都是因为总是排除 base-specifiers 和 mem-initializer-ids,如下所示:

template <typename T> struct X : T::type  { }; // always ok
Run Code Online (Sandbox Code Playgroud)

这没关系,因为,嗯,这需要是一种类型。这篇论文只是将这个逻辑(嗯,它必须是一种类型,所以我们假设它是一种类型)扩展到更多必须是类型的地方。

  • IIRC 我们已经在 C++11 中为基本说明符和 mem-initializer-ids 设置了“typename”_可选_。最初的“typename”提案不允许在不需要的地方使用它,但我们相信接受冗余的“typename”是无害的。 (7认同)

cig*_*ien 20

参考,从 c++20,在依赖名称明确是类型名称的上下文中,typename不再需要关键字。特别是:

在以下(顶级)decl-specifier-seq 中用作声明说明符的限定名称:

命名空间范围内的简单声明或函数定义