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

为什么我不需要指定

问题描述:

这部分代码在C ++ 20中编译(使用gcc 10.1),而在依赖类型std::vector<T>::iterator之前未使用typename关键字.为什么会编译?

This bit of code compiled in C++20 (using gcc 10.1) without using the typename keyword before the dependent type std::vector<T>::iterator. Why does it compile?

#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>;
}

代码游乐场

C ++ 20中的一项新功能是

One of the new features in C++20 is Down with typename.

在C ++ 17中,您必须在几乎所有与相关的上下文中提供typename关键字,以从值中消除类型的歧义.但是在C ++ 20中,此规则放松了很多.在需要具有类型的所有情况下,typename关键字不再是必需的.

In C++17, you had to provide the typename keyword in nearly all dependent contexts to disambiguate a type from a value. But in C++20, this rule is relaxed a lot. In all contexts where you need to have a type, the typename keyword is no longer mandatory.

一个这样的上下文就是类范围内的函数的返回类型,如您的示例所示.其他包括成员声明中的类型,using声明右侧的类型,lambda的参数声明,要传递给static_cast的类型,等等.有关完整列表,请参见本文.

One such context is the return type of a function in class scope, as in your example. Others include the type in a member declaration, the type on the right-hand side of a using declaration, the parameter declaration of a lambda, the type you're passing to static_cast, etc. See the paper for the full list.

几乎所有原因都是因为总是排除了base-specifier和mem-initializer-id,例如:

Nearly all because base-specifiers and mem-initializer-ids were always excluded, as in:

template <typename T> struct X : T::type  { }; // always ok

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

This is okay because, well, that needs to be a type. The paper simply extends this logic (well, it has to be a type, so let's just assume it's a type) to a lot more places that have to be types.