【问题标题】:User-Defined Deduction Guides in C++20C++20 中的用户定义推导指南
【发布时间】:2020-07-13 03:10:47
【问题描述】:

我正在使用std::variantstd::visit,使用如下所示的"overload" pattern

#include <iostream>
#include <variant>

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

int main(void) {
  std::variant<int, float> var;
  auto fs = overloaded {
    [](int var) {std::cout << "var is int" << std::endl;},
    [](float var) {std::cout << "var is float" << std::endl;}
  };
  var = 0;
  std::visit(fs, var);
  var = 0.0f;
  std::visit(fs, var);
}

在 cppreference 上,an example 说:

// explicit deduction guide (not needed as of C++20)
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

为什么在 C++20 中不再需要这个推导指南?删除类型推导指南会导致 compile to fail on all current compilers,但现在没有人完全支持 C++20,所以这并不意味着什么。谁能指出我讨论这个的规范部分?

【问题讨论】:

  • 它确实适用于gcc trunk
  • @cigien 感谢您指出这一点!我并不怀疑评论是正确的,只是想弄清楚 C++20 中发生了什么变化以使其合法。
  • @nickelpro。 P2082R1。支持即将推出的 gcc-11。

标签: c++ language-lawyer c++20 type-deduction


【解决方案1】:

此更改由 P1021R4 添加,特别是 P1816R0,添加了对聚合的类模板参数推导的支持。

具体的措辞可以在[over.match.class.deduct]/1 中找到,它基本上添加了聚合的隐式推导指南:

此外,如果定义了C,并且它的定义满足聚合类([dcl.init.aggr])的条件,并假设任何依赖基类都没有虚函数和虚基类,并且初始化器是一个非空的braced-init-list圆括号表达式列表,并且C 没有deduction-guides ,该集合包含一个附加的函数模板,称为聚合推导候选,定义如下。 令 x1,…,xn 为 braced-init-listinitializer-listdesignated-initializer-list 的元素,或表达式列表。 对于每个 xi,设 ei 是 C 的相应聚合元素,或者是它的一个(可能是递归的)子聚合之一,如果

  • 对于具有依赖的非数组类型或具有依赖于值的边界的数组类型的任何聚合元素,不考虑大括号省略,并且
  • 假设每个作为包扩展的非尾随聚合元素不对应于初始化列表中的任何元素,并且
  • 假定作为包扩展的尾随聚合元素对应于初始化列表的所有剩余元素(如果有)。

如果对于任何 xi 都没有这样的聚合元素 ei,则聚合推演候选不会添加到集合中。 聚合推导候选项如上从假设的构造函数 C(T1,…,Tn) 推导出来的,其中

  • 如果 ei 是数组类型且 xi 是花括号初始化列表或字符串文字,则 Ti 是对 ei 的声明类型的右值引用,并且
  • 否则,Ti 是 ei 的声明类型,

除了 Pj... 形式的附加参数包被插入到参数列表中的原始聚合元素位置中,该位置对应于每个 Pj 类型的非尾随聚合元素,因为它是参数包而被跳过,并且与作为包扩展(如果有)的尾随聚合元素相对应的尾随参数序列被替换为 Tn.... 形式的单个参数。

基本上,你之前必须写的演绎指南:

template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

现在只是脱离了语言。

【讨论】:

  • 链接的提案都没有从包装扩展中扣除的措辞。这似乎已在p2082r1 第 4 节中提出
猜你喜欢
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 2018-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多