【问题标题】:Why don't I need to specify "typename" before a dependent type in C++20?为什么我不需要在 C++20 中的依赖类型之前指定“typename”?
【发布时间】:2020-09-11 09:59:20
【问题描述】:

这段代码在 C++20 中编译(使用 gcc 10.1),在依赖类型 std::vector<T>::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>;
}

code playground

【问题讨论】:

  • 我有点惊讶标准会发现它模棱两可(因此,需要typename),因为(我认为......)它必须是在那里输入。可能要添加language-lawyer 标签。
  • C++20 允许删除一些类型名的使用。
  • @Eljay 它仍然需要知道它一种类型;)它是一种类型是如何定义/识别“那里”的一部分。或者,更确切地说,它曾经是。

标签: c++ templates language-lawyer c++20 typename


【解决方案1】:

C++20 中的一个新特性是Down with typename

在 C++17 中,您必须在几乎所有 相关上下文中提供 typename 关键字来区分类型和值。但是在 C++20 中,这个规则放松了很多。在所有需要类型的上下文中,typename 关键字不再是强制性的。

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


几乎都是因为 base-specifiers 和 mem-initializer-ids 总是被排除在外,如:

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

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

【讨论】:

  • IIRC 我们已经在 C++11 中为 base-specifiers 和 mem-initializer-ids 制作了 typename optional。最初的 typename 提案在任何不需要的地方都不允许它,但我们认为接受多余的 typename 是无害的。
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    • 2014-05-17
    • 2021-10-22
    • 2020-01-12
    • 2017-02-15
    • 1970-01-01
    相关资源
    最近更新 更多