User-Defined Deduction Guides in C++20

十年热恋 提交于 2021-02-05 05:57:18

问题


I'm working with std::variant and std::visit using the "overload" pattern that looks like this:

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

On cppreference, there's an example that says:

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

Why is this deduction guide no longer needed in C++20? Removing the type deduction guide causes the compile to fail on all current compilers, but no one fully supports C++20 right now so that doesn't mean anything. Can anyone point me to the part of the spec that discusses this?


回答1:


This change was added by P1021R4, specifically P1816R0, which added support for class template argument deduction for aggregates.

The specific wording can be found in [over.match.class.deduct]/1 which adds, basically, an implicit deduction guide for aggregates:

In addition, if C is defined and its definition satisfies the conditions for an aggregate class ([dcl.init.aggr]) with the assumption that any dependent base class has no virtual functions and no virtual base classes, and the initializer is a non-empty braced-init-list or parenthesized expression-list, and there are no deduction-guides for C, the set contains an additional function template, called the aggregate deduction candidate, defined as follows. Let x1,…,xn be the elements of the initializer-list or designated-initializer-list of the braced-init-list, or of the expression-list. For each xi, let ei be the corresponding aggregate element of C or of one of its (possibly recursive) subaggregates that would be initialized by xi ([dcl.init.aggr]) if

  • brace elision is not considered for any aggregate element that has a dependent non-array type or an array type with a value-dependent bound, and
  • each non-trailing aggregate element that is a pack expansion is assumed to correspond to no elements of the initializer list, and
  • a trailing aggregate element that is a pack expansion is assumed to correspond to all remaining elements of the initializer list (if any).

If there is no such aggregate element ei for any xi, the aggregate deduction candidate is not added to the set. The aggregate deduction candidate is derived as above from a hypothetical constructor C(T1,…,Tn), where

  • if ei is of array type and xi is a braced-init-list or string-literal, Ti is an rvalue reference to the declared type of ei, and
  • otherwise, Ti is the declared type of ei,

except that additional parameter packs of the form Pj... are inserted into the parameter list in their original aggregate element position corresponding to each non-trailing aggregate element of type Pj that was skipped because it was a parameter pack, and the trailing sequence of parameters corresponding to a trailing aggregate element that is a pack expansion (if any) is replaced by a single parameter of the form Tn....

Basically, the deduction-guide that you had to write before:

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

just falls out of the language now.



来源:https://stackoverflow.com/questions/62868708/user-defined-deduction-guides-in-c20

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!