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


70

这部分代码在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>;
}

代码游乐场


2
我对该标准会感到模棱两可感到有些惊讶(因此,required typename),因为(我认为...)那里一定一个类型。可能要添加language-lawyer标签。
Eljay

4
C ++ 20允许删除某些类型名称用法。
Jarod42年

3
@Eljay它仍然需要知道它一个类型;)它是如何定义/识别“那里”的一部分。或者说,它曾经是。
带翅膀的小行星

Answers:


62

C ++ 20的新功能之一是Downtypename

在C ++ 17中,您必须typename在几乎所有依赖上下文中提供关键字,才能从值中消除类型的歧义。但是在C ++ 20中,此规则放松了很多。在需要使用类型的所有上下文中,typename关键字不再是必需的。

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


几乎所有原因都是因为始终排除了基本说明符和mem-initializer-id,如:

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

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


7
IIRC我们已经在C ++ 11中为base-specifiers和mem-initializer-ids提供了typename 可选功能。最初的typename提议禁止在不需要的地方使用它,但是我们认为接受多余的提议是无害的typename
MSalters

19

引用开始,从c ++ 20开始,在从属名称明确为类型名的上下文中,typename不再需要该关键字。特别是:

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.