C++ 为什么不';t我需要具体说明“;typename";在C++;20?

C++ 为什么不';t我需要具体说明“;typename";在C++;20?,c++,templates,language-lawyer,c++20,typename,C++,Templates,Language Lawyer,C++20,Typename,这段代码是在C++20(使用gcc 10.1)中编译的,在依赖类型std::vector::iterator之前没有使用typename关键字。它为什么要编译 #include <vector> template<typename T> std::vector<T>::iterator // Why does this not require "typename" before it? f() { return {}; } int main() {

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

#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>;
}
#包括
模板
std::vector::iterator//为什么不需要在前面加上“typename”?
f(){return{};}
int main(){
自动fptr=&f;
}

C++20中的一个新特性是

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

一个这样的上下文是类作用域中函数的返回类型,如您的示例所示。其他包括成员声明中的类型、使用声明右侧的类型、lambda的参数声明、传递给
static\u cast
的类型等。有关完整列表,请参阅本文


†几乎所有原因都是因为基本说明符和mem初始值设定项ID始终被排除在外,如:

template <typename T> struct X : T::type  { }; // always ok
模板结构X:T::type{};//总是好的
这没关系,因为,嗯,这需要是一种类型。本文只是将这种逻辑(好吧,它必须是一个类型,所以让我们假设它是一个类型)扩展到更多必须是类型的地方

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

在(顶级)decl说明符序列中用作声明说明符的限定名称:

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


我有点惊讶标准会发现它模棱两可(因此,需要
typename
),因为(我认为…)它必须是那里的类型。可能需要添加
language
tag。C++20允许删除某些类型名用法。@Eljay它仍然需要知道它是一个类型;)作为一种类型,它是如何定义/识别“存在”的一部分。或者,更确切地说,它用于.IIRC,我们已经在C++11中为基本说明符和mem初始值设定项ID设置了
typename
可选。最初的
typename
提案在任何不需要的地方都不允许它,但我们认为接受冗余的
typename
是无害的。