<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<style type="text/css">/*<![CDATA[*/

body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }
consistent { font-weight: bold; color: #005100; }
inconsistent { font-weight: bold; color: #CC0000; }
meh { font-weight: bold; color: #FFAA00; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5empadding-right: 0.5em; ; }

blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3; padding: 0.5em; }

blockquote pre em { font-family: normal }

table, th, td { border: 1px solid black; }

/*]]>*/
</style>

<title>A Single Generalization of std::invoke, std::apply, and std::visit</title>
</head>
<body>

<p style="text-align: right; float: right">
ISO/IEC JTC1 SC22 WG21<br>
Document Number: P0376R0<br>
Audience: Library Evolution Working Group<br>
Matt Calabrese (<a href="mailto:metaprogrammingtheworld@gmail.com">metaprogrammingtheworld@gmail.com</a>)<br>
2016-05-28<br>
</p>

<h1>A Single Generalization of std::invoke, std::apply, and std::visit</h1>

<h2><a id="Abstract">Abstract</a></h2>
<p>This paper presents a single generalization of <code>std::invoke</code>, <code>std::apply</code>, and the proposed <code>std::visit</code> <sup><a href="#References_Variant">[1]</a></sup> by specifying a template named <code>std::call</code> that takes a standard <code>Callable</code> followed by any number of arguments and/or "argument providers," the latter of which act as descriptions of portions of an argument list that are to be substituted in-place when the <code>Callable</code> is invoked. Each generated argument list portion may be any number of arguments with any combination of types, and the precise argument list and its values may even depend on runtime data. Due to the generality of the substitution mechanism, the facility allows argument providers such as ones that can unpack tuples at arbitrary positions in a larger argument list, as well as argument providers that can forward along the active field of a variant. In addition to these familiar operations, further argument providers are presented that do not directly correspond to existing library facilities.</p>

<h2><a id="Overview">Overview</a></h2>

<p>The ideas described in this paper are relatively simple to understand at a high level and aid both in the expressive power of C++ and in code readability. Before going into more detailed motivating cases and implementation, the facility is easiest to describe with a set of usage examples. In the following <code>main</code> function, each invocation of <code>output_values</code> is given an equivalent argument list, although each time it is formed in a different way.</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#696969; '>// This is just a Callable we will use for all of the following examples.</span>
<span style='color:#696969; '>// It takes a stream and a series of arguments, outputting each.</span>
<span style='color:#800000; font-weight:bold; '>constexpr</span> <span style='color:#800000; font-weight:bold; '>auto</span> output_values <span style='color:#808030; '>=</span>
  <span style='color:#808030; '>[</span><span style='color:#808030; '>]</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>&amp;</span> os<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>const</span> <span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> args<span style='color:#808030; '>)</span> <span style='color:#808030; '>-</span><span style='color:#808030; '>></span> <span style='color:#800000; font-weight:bold; '>decltype</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#808030; '>(</span>os <span style='color:#808030; '>&lt;</span><span style='color:#808030; '>&lt;</span> <span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> <span style='color:#808030; '>&lt;</span><span style='color:#808030; '>&lt;</span> args<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// In the following function, every time std::call is used, output_values is</span>
<span style='color:#696969; '>// ultimately invoked with equivalent values.</span>
<span style='color:#800000; font-weight:bold; '>int</span> <span style='color:#400000; '>main</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  <span style='color:#696969; '>// In its simplest usage, std::call does what std::invoke does.</span>
  <span style='color:#696969; '>// It just invokes the Callable with the specified arguments.</span>
  <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#008c00; '>5</span><span style='color:#808030; '>,</span> <span style='color:#008000; '>3.5</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span>“Hello”<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>

  <span style='color:#696969; '>// It can also be used with a provider that unpacks tuples.</span>
  <span style='color:#696969; '>// Note that std::cout is not a member of the tuple, so it is</span>
  <span style='color:#696969; '>// simply forwarded to the Callable as-is.</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>auto</span> args <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>make_tuple<span style='color:#808030; '>(</span><span style='color:#008c00; '>5</span><span style='color:#808030; '>,</span> <span style='color:#008000; '>3.5</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span>“Hello”<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>unpack<span style='color:#808030; '>(</span>args<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>

  <span style='color:#696969; '>// It can also unpack a tuple, followed by additional arguments.</span>
  <span style='color:#696969; '>// Note that neither std::cout nor the string are members of the tuple.</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>auto</span> args <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>make_tuple<span style='color:#808030; '>(</span><span style='color:#008c00; '>5</span><span style='color:#808030; '>,</span> <span style='color:#008000; '>3.5</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>unpack<span style='color:#808030; '>(</span>args<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span>“Hello”<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>

  <span style='color:#696969; '>// It can unpack multiple tuples in succession.</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>tuple<span style='color:#800080; '>&lt;</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>ostream</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>int</span><span style='color:#800080; '>></span> head_args<span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#008c00; '>5</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>auto</span> tail_args <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>make_tuple<span style='color:#808030; '>(</span><span style='color:#008000; '>3.5</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span>“Hello”<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>unpack<span style='color:#808030; '>(</span>head_args<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>unpack<span style='color:#808030; '>(</span>tail_args<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>

  <span style='color:#696969; '>// It can pass along a reference to the currently active field of a variant.</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>variant<span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#800080; '>></span> arg0 <span style='color:#808030; '>=</span> <span style='color:#008c00; '>5</span><span style='color:#808030; '>,</span> arg2 <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span>“Hello”<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>arg0<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span>
                                        <span style='color:#008000; '>3.5</span><span style='color:#808030; '>,</span>
                                        <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>arg2<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>

  <span style='color:#696969; '>// It can access a tuple with a runtime index.</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>auto</span> args <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>make_tuple<span style='color:#808030; '>(</span><span style='color:#008c00; '>5</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span>“Hello”<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>access_tuple<span style='color:#808030; '>(</span>args<span style='color:#808030; '>,</span> <span style='color:#008c00; '>0</span><span style='color:#808030; '>)</span><span style='color:#808030; '>,</span>
                                        <span style='color:#008000; '>3.5</span><span style='color:#808030; '>,</span>
                                        <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>access_tuple<span style='color:#808030; '>(</span>args<span style='color:#808030; '>,</span> <span style='color:#008c00; '>1</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>

  <span style='color:#696969; '>// It can work with multiple different kinds of providers in the same call.</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>variant<span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#800080; '>></span> head_arg <span style='color:#808030; '>=</span> <span style='color:#008c00; '>5</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>auto</span> tail_args <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>make_tuple<span style='color:#808030; '>(</span><span style='color:#008000; '>3.5</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span>“Hello”<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>head_arg<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>unpack<span style='color:#808030; '>(</span>tail_args<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>

  <span style='color:#696969; '>// It can work with providers that are composed</span>
  <span style='color:#696969; '>// (i.e. forward along the active field of each element</span>
  <span style='color:#696969; '>// of an unpacked tuple of variants).</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>using</span> variant_t <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>variant<span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>double</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#800080; '>></span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>auto</span> tail_args <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>make_tuple<span style='color:#808030; '>(</span>variant_t<span style='color:#808030; '>(</span><span style='color:#008000; '>3.5</span><span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> variant_t<span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span>“Hello”<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#008c00; '>5</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>unpack<span style='color:#808030; '>(</span>tail_args<span style='color:#808030; '>)</span> <span style='color:#808030; '>|</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>

  <span style='color:#696969; '>// It can deduce a return type for arbitrarily complex compositions, including</span>
  <span style='color:#696969; '>// ones that involve variant access or tuple access with a run-time index.</span>
  <span style='color:#696969; '>// By default, if all possible paths do not have the same exact return type,</span>
  <span style='color:#696969; '>// then substitution will fail.</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>variant<span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#800080; '>></span> arg0 <span style='color:#808030; '>=</span> <span style='color:#008c00; '>5</span><span style='color:#808030; '>,</span> arg2 <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span>“Hello”<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>&amp;</span> result <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>arg0<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span>
                                                       <span style='color:#008000; '>3.5</span><span style='color:#808030; '>,</span>
                                                       <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>arg2<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    static_assert<span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>is_same_v<span style='color:#800080; '>&lt;</span>decltype<span style='color:#808030; '>(</span>result<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>ostream</span><span style='color:#808030; '>&amp;</span><span style='color:#800080; '>></span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>

  <span style='color:#696969; '>// A return type can be explicitly specified to avoid automatic deduction.</span>
  <span style='color:#696969; '>// This is useful to force a different type or simply to reduce compile-times</span>
  <span style='color:#696969; '>// when dealing with sufficiently complicated invocations (such as access of</span>
  <span style='color:#696969; '>// several different variants in a single call).</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>variant<span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#800080; '>></span> arg0 <span style='color:#808030; '>=</span> <span style='color:#008c00; '>5</span><span style='color:#800080; '>;</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>void</span><span style='color:#800080; '>></span><span style='color:#808030; '>(</span>output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>arg0<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#008000; '>3.5</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span>“Hello”<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>

  <span style='color:#696969; '>// A return type deducer can be explicitly specified if the default behavior</span>
  <span style='color:#696969; '>// is not suitable. A deducer is just a variadic template that is internally</span>
  <span style='color:#696969; '>// instantiated with the return type of each potential invocation.</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>variant<span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>int</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#800080; '>></span> arg0 <span style='color:#808030; '>=</span> <span style='color:#008c00; '>5</span><span style='color:#800080; '>;</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#800080; '>&lt;</span>some_user_defined_common_type_t<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>
      output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>arg0<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#008000; '>3.5</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span>“Hello”<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>
<span style='color:#800080; '>}</span>
</pre>

<h2><a id="Motivation">Motivation</a></h2>
<p>The primary motivation for a facility such as this comes from the desire for developers to reuse existing functions whenever possible without having to manually create lambdas. This comes up frequently in order to do things such as unpack only a portion of an argument list (as is often necessary when using <code>std::apply</code>), or forward along the active field of a variant to only one argument of a larger parameter list (as is often necessary when using facilities like the proposed <code>std::visit</code>). Expanding tuples in-place in an argument list is not an uncommon practice in other mainstream languages, such as Python <sup><a href="#References_PythonUnpacking">[2]</a></sup>, and forwarding the active field of a variant to an existing function is also not unheard of, even in statically-typed languages (an example of this is the dispatch operator of the Clay programming language <sup><a href="#References_ClayDispatchOp">[3]</a></sup>).</p>

<h3><a id="Apply">Complications of std::apply</a></h3>
<p>Assuming the <code>output_values</code> function that was presented earlier, consider what is required by users to invoke the function when all but the stream argument are an element of a tuple. The following is an example using <code>std::apply</code> followed by what is required when using <code>std::call</code>.  The version using the proposed <code>std::call</code> is more concise and considerably more readable:</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>auto</span> args <span style='color:#808030; '>=</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>make_tuple<span style='color:#808030; '>(</span><span style='color:#008c00; '>5</span><span style='color:#808030; '>,</span> <span style='color:#008000; '>3.5</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>string</span><span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>Hello</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    
<span style='color:#696969; '>// This is what is required using std::apply.</span>
<span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>apply<span style='color:#808030; '>(</span><span style='color:#808030; '>[</span><span style='color:#808030; '>]</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>const</span> <span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> args<span style='color:#808030; '>)</span> <span style='color:#808030; '>-</span><span style='color:#808030; '>></span> decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
             <span style='color:#800000; font-weight:bold; '>return</span> output_values<span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> args<span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
           <span style='color:#800080; '>}</span><span style='color:#808030; '>,</span>
           args<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  
<span style='color:#696969; '>// This is what is required using the proposed std::call.</span>
<span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>output_values<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>cout</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>unpack<span style='color:#808030; '>(</span>args<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
</pre>

<h3><a id="Visit">Complications of std::visit</a></h3>
<p>A similar kind of situation comes up when dealing with variants. Consider the following more tangible example, which is based on real-world code.</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>struct</span> line <span style='color:#800080; '>{</span> <span style='color:#696969; '>/*...*/</span> <span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>struct</span> circle <span style='color:#800080; '>{</span> <span style='color:#696969; '>/*...*/</span> <span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
<span style='color:#800000; font-weight:bold; '>struct</span> square <span style='color:#800080; '>{</span> <span style='color:#696969; '>/*...*/</span> <span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#800000; font-weight:bold; '>struct</span> in_collision_fun <span style='color:#800080; '>{</span>
  <span style='color:#696969; '>// Each of these returns true if the arguments are in collision</span>
  <span style='color:#800000; font-weight:bold; '>bool</span> <span style='color:#800000; font-weight:bold; '>operator</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>(</span>line<span style='color:#808030; '>,</span> line<span style='color:#808030; '>)</span> <span style='color:#800000; font-weight:bold; '>const</span> <span style='color:#800080; '>{</span> <span style='color:#696969; '>/*...*/</span> <span style='color:#800080; '>}</span>
  <span style='color:#800000; font-weight:bold; '>bool</span> <span style='color:#800000; font-weight:bold; '>operator</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>(</span>line<span style='color:#808030; '>,</span> circle<span style='color:#808030; '>)</span> <span style='color:#800000; font-weight:bold; '>const</span> <span style='color:#800080; '>{</span> <span style='color:#696969; '>/*...*/</span> <span style='color:#800080; '>}</span>
  <span style='color:#696969; '>// ... similar for each combination ...</span>
<span style='color:#800080; '>}</span> <span style='color:#800000; font-weight:bold; '>constexpr</span> in_collision<span style='color:#800080; '>{</span><span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#800000; font-weight:bold; '>int</span> <span style='color:#400000; '>main</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  circle my_circle<span style='color:#808030; '>(</span><span style='color:#696969; '>/*...*/</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  square my_square<span style='color:#808030; '>(</span><span style='color:#696969; '>/*...*/</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>

  variant<span style='color:#800080; '>&lt;</span>line<span style='color:#808030; '>,</span> circle<span style='color:#808030; '>,</span> square<span style='color:#800080; '>></span> my_circle_variant <span style='color:#808030; '>=</span> my_circle<span style='color:#808030; '>,</span>
                                my_square_variant <span style='color:#808030; '>=</span> my_square<span style='color:#800080; '>;</span>

  <span style='color:#696969; '>// This block uses std::visit</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#696969; '>// Both arguments are variants.</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>visit<span style='color:#808030; '>(</span>in_collision<span style='color:#808030; '>,</span> my_square_variant<span style='color:#808030; '>,</span> my_circle_variant<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>

    <span style='color:#696969; '>// The first argument is an expanded variant.</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>visit<span style='color:#808030; '>(</span><span style='color:#808030; '>[</span><span style='color:#808030; '>&amp;</span>my_circle<span style='color:#808030; '>]</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>const</span> <span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>&amp;</span> first<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
                 <span style='color:#800000; font-weight:bold; '>return</span> in_collision<span style='color:#808030; '>(</span>first<span style='color:#808030; '>,</span> my_circle<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
               <span style='color:#800080; '>}</span><span style='color:#808030; '>,</span> my_square_variant<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    
    <span style='color:#696969; '>// The second argument is an expanded variant.</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>visit<span style='color:#808030; '>(</span><span style='color:#808030; '>[</span><span style='color:#808030; '>&amp;</span>my_square<span style='color:#808030; '>]</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>const</span> <span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>&amp;</span> second<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
                 <span style='color:#800000; font-weight:bold; '>return</span> in_collision<span style='color:#808030; '>(</span>my_square<span style='color:#808030; '>,</span> second<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
               <span style='color:#800080; '>}</span><span style='color:#808030; '>,</span> my_circle_variant<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>

  <span style='color:#696969; '>// This block uses the proposed std::call</span>
  <span style='color:#800080; '>{</span>
    <span style='color:#696969; '>// Both arguments are variants.</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>in_collision<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>my_square_variant<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span>
                            <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>my_circle_variant<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>

    <span style='color:#696969; '>// The first argument is an expanded variant.</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>in_collision<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>my_square_variant<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span>
                            my_circle<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>

    <span style='color:#696969; '>// The second argument is an expanded variant.</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>in_collision<span style='color:#808030; '>,</span> my_square<span style='color:#808030; '>,</span>
                            <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>my_circle_variant<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>
<span style='color:#800080; '>}</span>
</pre>

<h3><a id="Deserialization">Variant Deserialization</a></h3>
<p>Serialization and deserialization of a variant is frequently done by serializing the integer discriminator of the variant, followed by serializing the corresponding field. Deserialization works by deserializing the integer discriminator and then deserializing an instance of the field type that corresponds to the discriminator. While this is very simple to think about at a high level, this deserialization process is not directly implementable using a facility like <code>std::visit</code>. It is actually surprisingly complicated to implement in a generic manner without additional facilities akin to the accepted-but-never-added Boost.Switch Library <sup><a href="#References_BoostSwitch">[4]</a></sup>. However, this deserialization process can be easily implemented with <code>std::call</code>. In order to implement this functionality, the developer can use an argument provider that generates a <code>std::integral_constant</code> based on a runtime value (an argument provider named <code>std::to_constant_discriminator</code> is specifically included for this kind of purpose). An example of this can be seen below:</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> Archive<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> V<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>void</span> serialize_variant<span style='color:#808030; '>(</span>Archive<span style='color:#808030; '>&amp;</span> archive<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>const</span> V<span style='color:#808030; '>&amp;</span> v<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  serialize<span style='color:#808030; '>(</span>archive<span style='color:#808030; '>,</span> v<span style='color:#808030; '>.</span>which<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>serialize<span style='color:#808030; '>,</span> archive<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>active_field_of<span style='color:#808030; '>(</span>v<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#696969; '>// A function that deserializes into a variant when the field</span>
<span style='color:#696969; '>// discriminator is known at compile-time.</span>
<span style='color:#696969; '>// "discriminator" here is an instantiation of std::integral_constant.</span>
<span style='color:#800000; font-weight:bold; '>constexpr</span> <span style='color:#800000; font-weight:bold; '>auto</span> deserialize_variant_field <span style='color:#808030; '>=</span>
  <span style='color:#808030; '>[</span><span style='color:#808030; '>]</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>&amp;</span> archive<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>&amp;</span> variant_<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>auto</span> discriminator<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
    variant_<span style='color:#808030; '>.</span><span style='color:#800000; font-weight:bold; '>template</span> emplace<span style='color:#808030; '>&lt;</span>discriminator<span style='color:#808030; '>.</span>value<span style='color:#808030; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    deserialize_into<span style='color:#808030; '>(</span>archive<span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>get<span style='color:#808030; '>&lt;</span>discriminator<span style='color:#808030; '>.</span>value<span style='color:#808030; '>></span><span style='color:#808030; '>(</span>variant_<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> Archive<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> V<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>void</span> deserialize_variant<span style='color:#808030; '>(</span>Archive<span style='color:#808030; '>&amp;</span> archive<span style='color:#808030; '>,</span> V<span style='color:#808030; '>&amp;</span> variant_<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>(</span>deserialize_variant_field<span style='color:#808030; '>,</span>
    archive<span style='color:#808030; '>,</span>
    variant_<span style='color:#808030; '>,</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>to_constant_discriminator<span style='color:#800080; '>&lt;</span>V<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>deserialize<span style='color:#800080; '>&lt;</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>size_t</span><span style='color:#800080; '>></span><span style='color:#808030; '>(</span>archive<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
</pre>

<h2><a id="ProposedFacilities">Proposed Facilities</a></h2>
<p>Due to the nature of the templates involved, it is rather difficult to express a complete interface specification. What follows is an informal specification that should evolve considerably if the functionality that <code>std::call</code> provides is deemed valuable by the committee.</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#696969; '>// If all of T... are the same type as H, yields H,</span>
<span style='color:#696969; '>// otherwise substitution will fail.</span>
<span style='color:#696969; '>// This is used as the default return type deducer for std::call.</span>
<span style='color:#696969; '>// Ultimately this may be left as an implementation detail and not exposed,</span>
<span style='color:#696969; '>// but it may be a generally useful facility to specify for users.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> H<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> T<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>using</span> same_type_or_fail <span style='color:#808030; '>=</span> <span style='color:#696969; '>/*...*/</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// Invoke "fun" with the generated argument list.</span>
<span style='color:#696969; '>// ReturnTypeDeducer is passed along to each provider's</span>
<span style='color:#696969; '>// "provide" function (described later).</span>
<span style='color:#696969; '>// Substitution will fail if the call to "fun" with any of the</span>
<span style='color:#696969; '>// possible generated argument lists would fail substitution.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#800080; '>></span> <span style='color:#800000; font-weight:bold; '>class</span> ReturnTypeDeducer <span style='color:#808030; '>=</span> same_type_or_fail<span style='color:#808030; '>,</span>
          <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> Providers<span style='color:#800080; '>></span>
constexpr <span style='color:#800000; font-weight:bold; '>auto</span> call<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>,</span> Providers<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> providers<span style='color:#808030; '>)</span> noexcept<span style='color:#808030; '>(</span><span style='color:#696969; '>/*deduced*/</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>-</span><span style='color:#808030; '>></span> <span style='color:#696969; '>/*deduced*/</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// Invoke "fun" with the generated argument list.</span>
<span style='color:#696969; '>// This is equivalent to invoking std::call with a ReturnTypeDeducer that</span>
<span style='color:#696969; '>// always yields "ReturnType".</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> ReturnType<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> Providers<span style='color:#800080; '>></span>
constexpr <span style='color:#800000; font-weight:bold; '>auto</span> call<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>,</span> Providers<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> providers<span style='color:#808030; '>)</span> noexcept<span style='color:#808030; '>(</span><span style='color:#696969; '>/*deduced*/</span><span style='color:#808030; '>)</span> <span style='color:#808030; '>-</span><span style='color:#808030; '>></span> <span style='color:#696969; '>/*deduced*/</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// All "argument providers" are an instantiation of this template.</span>
<span style='color:#696969; '>// The Provider argument must be a type that has a static member function</span>
<span style='color:#696969; '>// template called "provide" that is compatible with the following:</span>
<span style='color:#696969; '>//</span>
<span style='color:#696969; '>//     template &lt;template &lt;class...> class ReturnTypeDeducer, class Fun, class Self></span>
<span style='color:#696969; '>//     static constexpr auto provide(Fun&amp;&amp; fun, Self&amp;&amp; self) -> /*implementation-dependent*/;</span>
<span style='color:#696969; '>//</span>
<span style='color:#696969; '>// The provide function is the customization point that describes how</span>
<span style='color:#696969; '>// an argument provider generates its portion of the argument list.</span>
<span style='color:#696969; '>// The developer of the provide function does this by invoking</span>
<span style='color:#696969; '>// the function object "fun" with any number of arguments of any type.</span>
<span style='color:#696969; '>// The result of that function call should be returned by provide.</span>
<span style='color:#696969; '>// In the case where the provide function may invoke "fun" with different</span>
<span style='color:#696969; '>// arguments depending on some runtime condition (such as when implementing</span>
<span style='color:#696969; '>// an argument provider that accesses the active field of a variant), then</span>
<span style='color:#696969; '>// ReturnTypeDeducer must be instantiated with the decltype of the result of</span>
<span style='color:#696969; '>// each possible call, and the type that is yielded must be used as the</span>
<span style='color:#696969; '>// return type of the provide function.</span>
<span style='color:#696969; '>//</span>
<span style='color:#696969; '>// "Self" here is a cv-reference-qualified Provider. The provide function</span>
<span style='color:#696969; '>// is static so that it is easy for users to properly forward internal data</span>
<span style='color:#696969; '>// without the need for the user to write multiple overloads.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> Provider<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> argument_provider <span style='color:#800080; '>{</span> Provider <span style='color:#696969; '>/*unspecified*/</span><span style='color:#800080; '>;</span> <span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// An argument provider that evaluates a user-specified provider and forwards</span>
<span style='color:#696969; '>// those arguments along to the user-specified callable. This is used</span>
<span style='color:#696969; '>// for argument provider composition (such as fully unpacking a tuple of</span>
<span style='color:#696969; '>// tuples). Instances of this are the result of the | operator used in the</span>
<span style='color:#696969; '>// earlier examples and shown below.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> Provider<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Callable<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>using</span> composed_argument_provider <span style='color:#808030; '>=</span> argument_provider<span style='color:#808030; '>&lt;</span><span style='color:#696969; '>/*unspecified*/</span><span style='color:#808030; '>></span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// Creates a composed argument provider.</span>
<span style='color:#696969; '>// There should be an overload where the left operand is a reference-to-const</span>
<span style='color:#696969; '>// and also an overloaded where the left operand is an rvalue reference.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> Provider<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Callable<span style='color:#800080; '>></span>
constexpr composed_argument_provider<span style='color:#800080; '>&lt;</span>argument_provider<span style='color:#800080; '>&lt;</span>Provider<span style='color:#800080; '>></span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>,</span> Callable<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>operator</span> <span style='color:#808030; '>|</span><span style='color:#808030; '>(</span>argument_provider<span style='color:#800080; '>&lt;</span>Provider<span style='color:#800080; '>></span><span style='color:#808030; '>&amp;</span> provider<span style='color:#808030; '>,</span>
           Callable<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> next_function<span style='color:#808030; '>)</span> noexcept<span style='color:#800080; '>;</span>
</pre>

<p>The above specification details the core parts of the facility. Below is a small set of suggested argument providers to be included with the facility.</p>

<p>
  <ul>
    <li><code>unpack(T&& tuple)</code>: Perfect-forwards the N elements of a tuple as N arguments.</li>
    <li><code>active_field_of(V&& var)</code>: Perfect-forwards the active field of a variant.</li>
    <li><code>access_tuple(T&& var, std::size_t index)</code>: Perfect-forwards the element of the tuple at position "index".</li>
    <li><code>to_constant_in_range&lt;class T, T Begin, T End&gt;(U&& value)</code>: Takes a runtime value and provides the corresponding <code>std::integral_constant</code>.</li>
    <li><code>to_constant_discriminator&lt;class Variant&gt;(std::size_t discriminator)</code>: Equivalent to <code>to_constant_in_range</code> where the range is [0, variant-arity).</li>
    <li><code>to_constant_tuple_index&lt;class Tuple&gt;(std::size_t index)</code>: Equivalent to <code>to_constant_in_range</code> where the range is [0, tuple-size).</li>
  </ul>
</p>

<p>These argument providers have all been used at the top level of the examples presented in this paper, with the exception of <code>std::to_constant_in_range</code>. This argument provider is proposed because it is useful internally for most argument providers that produce different arguments depending on a runtime value (such as <code>std::active_field_of</code>, <code>std::access_tuple</code>, and <code>std::to_constant_discriminator</code>). Because of this, it should be considered important as a means for people to more easily construct their own argument provider types.</p>

<p>The <code>std::call</code> facility opens the door for limitless kinds of argument providers, though only a small handful were presented. It is expected that if this facility is accepted, user-space argument providers would be developed and used. The following is a selection of additional general-purpose argument providers that are useful, but not essential to the most common motivating cases and so they are not currently proposed. This is not an exhaustive list:</p>

<p>
  <ul>
    <li><code>group(T&&... args)</code>: Perfect-forwards <code>args</code> (useful with the <code>|</code> operator).</li>
    <li><code>identity(T&& arg)</code>: Perfect-forwards <code>arg</code> (same as <code>group</code> with one argument, analogous uses to <code>boost::protect</code>).</li>
    <li><code>fan(P&& provider, C&&... callables)</code>: Generates the provider's arguments and passes all of those arguments to each of <code>callables</code>.</li>
    <li><code>eat(T&&... args)</code>: Produces an empty list of arguments (useful during composition).</li>
  </ul>
</p>

<h2><a id="Implementation">Implementation Samples</a></h2>
<p>Because the implementation of these facilities may not be immediately obvious, the following are example definitions of a few of the facilities.</p>

<h3><a id="CallImplementation">Example std::call Implementation</a></h3>
<p>The following is a simplified definition of <code>std::call</code> lacking <code>noexcept</code> deduction, desirable SFINAE behavior, and special-casing for <code>void</code> returns.</p>
<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> Provider<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> argument_provider <span style='color:#800080; '>{</span> Provider impl<span style='color:#800080; '>;</span> <span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// Implementation details</span>
<span style='color:#800000; font-weight:bold; '>namespace</span> __detail <span style='color:#800080; '>{</span>

<span style='color:#696969; '>// A trait used internally to either expand an argument provider into its</span>
<span style='color:#696969; '>// generated arguments, or directly forward an argument along if it is not</span>
<span style='color:#696969; '>// an instantiation of argument_provider.</span>
<span style='color:#696969; '>// The default-definition here is the fall-back for when a given argument</span>
<span style='color:#696969; '>// is not an instantiation of argument_provider.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> T<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> argument_provider_traits <span style='color:#800080; '>{</span>
  <span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#800080; '>></span> <span style='color:#800000; font-weight:bold; '>class</span> ReturnTypeDeducer<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> U<span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>static</span> constexpr decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> provide<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>,</span> U<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> <span style='color:#400000; '>arg</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>)</span><span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>U<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#400000; '>arg</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
    
<span style='color:#696969; '>// The partial specialization of the above trait for an argument_provider,</span>
<span style='color:#696969; '>// which just forwards the invocation to the user-provided customization point.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> Provider<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> argument_provider_traits<span style='color:#800080; '>&lt;</span>argument_provider<span style='color:#808030; '>&lt;</span>Provider<span style='color:#808030; '>></span><span style='color:#800080; '>></span> <span style='color:#800080; '>{</span>
  <span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#800080; '>></span> <span style='color:#800000; font-weight:bold; '>class</span> ReturnTypeDeducer<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> U<span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>static</span> constexpr decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> provide<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>,</span> U<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> <span style='color:#400000; '>arg</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>return</span> Provider<span style='color:#800080; '>::</span><span style='color:#800000; font-weight:bold; '>template</span> provide<span style='color:#800080; '>&lt;</span>ReturnTypeDeducer<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span>
                                                         <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>U<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#400000; '>arg</span><span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>impl<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#696969; '>// Encapsulates a template that can be used as a ReturnTypeDeducer that</span>
<span style='color:#696969; '>// always yields T.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> T<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> always_return <span style='color:#800080; '>{</span>
  <span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>using</span> type <span style='color:#808030; '>=</span> T<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>

<span style='color:#800080; '>}</span>  <span style='color:#696969; '>// End __details namespace</span>

<span style='color:#696969; '>// The terminating case of the call function with an explicitly-specified</span>
<span style='color:#696969; '>// return type and when “fun” is invoked with no arguments.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> ReturnType<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#800080; '>></span>
constexpr ReturnType call<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>)</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#696969; '>// The terminating case of the call function with an explicitly-specified</span>
<span style='color:#696969; '>// ReturnTypeDeducer and when “fun” is invoked with no arguments.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#800080; '>></span> <span style='color:#800000; font-weight:bold; '>class</span> ReturnTypeDeducer <span style='color:#808030; '>=</span> same_type_or_fail<span style='color:#808030; '>,</span>
          <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#800080; '>></span>
constexpr decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> call<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  <span style='color:#696969; '>// Just call the function, being sure to use the return type deducer.</span>
  <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#808030; '>&lt;</span>ReturnTypeDeducer<span style='color:#808030; '>&lt;</span>decltype<span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>declval<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#808030; '>></span><span style='color:#808030; '>></span><span style='color:#808030; '>(</span>
      <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#696969; '>// Primary, recursive definition when "call" is given a ReturnTypeDeducer and</span>
<span style='color:#696969; '>// some number of arguments or argument_providers >= 1.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#800080; '>></span> <span style='color:#800000; font-weight:bold; '>class</span> ReturnTypeDeducer <span style='color:#808030; '>=</span> same_type_or_fail<span style='color:#808030; '>,</span>
          <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Head<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> Tail<span style='color:#800080; '>></span>
constexpr decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> call<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>,</span> Head<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> head<span style='color:#808030; '>,</span> Tail<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> tail<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  <span style='color:#800000; font-weight:bold; '>return</span> __detail<span style='color:#800080; '>::</span>argument_provider_traits<span style='color:#808030; '>&lt;</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>decay_t<span style='color:#808030; '>&lt;</span>Head<span style='color:#808030; '>></span><span style='color:#808030; '>></span>
      <span style='color:#800080; '>::</span><span style='color:#800000; font-weight:bold; '>template</span> provide<span style='color:#800080; '>&lt;</span>ReturnTypeDeducer<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>
    <span style='color:#696969; '>// The customization point for “head” may use "head" to provide any</span>
    <span style='color:#696969; '>// number of arguments. It communicates the generated arguments by</span>
    <span style='color:#696969; '>// passing those arguments to the lamba that we give it here.</span>
    <span style='color:#808030; '>[</span><span style='color:#808030; '>&amp;</span>fun<span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span>tail<span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>]</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> expanded_head<span style='color:#808030; '>)</span> <span style='color:#808030; '>-</span><span style='color:#808030; '>></span> decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
      <span style='color:#696969; '>// The lambda we give it recurses into “call” with a lambda that</span>
      <span style='color:#696969; '>// captures those arguments that were generated by "head". It takes</span>
      <span style='color:#696969; '>// as parameters the result of the expanded tail arguments.</span>
      <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#800080; '>&lt;</span>ReturnTypeDeducer<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>
        <span style='color:#808030; '>[</span><span style='color:#808030; '>&amp;</span>fun<span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span>expanded_head<span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>]</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> expanded_tail<span style='color:#808030; '>)</span> <span style='color:#808030; '>-</span><span style='color:#808030; '>></span> decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
          <span style='color:#696969; '>// At this point, we have the fully generated argument list,</span>
          <span style='color:#696969; '>// so we can invoke the original function.</span>
          <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>invoke<span style='color:#808030; '>(</span>
            <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span>
            <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>decltype<span style='color:#808030; '>(</span>expanded_head<span style='color:#808030; '>)</span><span style='color:#800080; '>></span><span style='color:#808030; '>(</span>expanded_head<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>,</span>
            <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>decltype<span style='color:#808030; '>(</span>expanded_tail<span style='color:#808030; '>)</span><span style='color:#800080; '>></span><span style='color:#808030; '>(</span>expanded_tail<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
        <span style='color:#800080; '>}</span><span style='color:#808030; '>,</span>
        <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Tail<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>tail<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span><span style='color:#808030; '>,</span>
    <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Head<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>head<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#696969; '>// Primary, definition when "call" is given an explicit return type and</span>
<span style='color:#696969; '>// some number of arguments or argument_providers >= 1.</span>
<span style='color:#696969; '>// This just invokes std::call with a ReturnTypeDeducer that always</span>
<span style='color:#696969; '>// yields ReturnType.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> ReturnType<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Head<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> Tail<span style='color:#800080; '>></span>
constexpr decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> call<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>,</span> Head<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> head<span style='color:#808030; '>,</span> Tail<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> tail<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#800080; '>&lt;</span>__detail<span style='color:#800080; '>::</span>always_return<span style='color:#800080; '>&lt;</span>ReturnType<span style='color:#800080; '>></span><span style='color:#800080; '>::</span><span style='color:#800000; font-weight:bold; '>template</span> type<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>
      <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Head<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>head<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Tail<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>tail<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>
</pre>

<h3><a id="UnpackImplementation">std::unpack Implementation</a></h3>
<p>The following is an example implementation of <code>std::unpack</code> using <code>std::apply</code> internally for brevity and eliding SFINAE exploitation and conditional <code>noexcept</code>. The code below is the type that would be used as a template parameter to <code>std::argument_provider</code>.</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> T<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> unpack_impl <span style='color:#800080; '>{</span>
  <span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#800080; '>></span> <span style='color:#800000; font-weight:bold; '>class</span> ReturnTypeDeducer<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> U<span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>static</span> constexpr decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> provide<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>,</span> U<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> <span style='color:#400000; '>arg</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
      <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>apply<span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>U<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#400000; '>arg</span><span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>tup<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>

  T<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> tup<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
</pre>

<h3><a id="AccessTupleImplementation">std::access_tuple Implementation</a></h3>
<p>The following is an example implementation of accessing a tuple with a runtime value. Internally it uses <code>std::to_constant_tuple_index</code>, which is built on <code>std::to_constant_in_range</code>. <code>std::to_constant_in_range</code> does the heavy lifting for this and other argument providers that depend on runtime data. Its implementation will be shown later.</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> T<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> I<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> access_tuple_impl <span style='color:#800080; '>{</span>
  <span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#800080; '>></span> <span style='color:#800000; font-weight:bold; '>class</span> ReturnTypeDeducer<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Self<span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>static</span> constexpr decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> provide<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>,</span> Self<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> self<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
    <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>call<span style='color:#800080; '>&lt;</span>ReturnTypeDeducer<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>
      <span style='color:#808030; '>[</span><span style='color:#808030; '>&amp;</span>fun<span style='color:#808030; '>,</span> <span style='color:#808030; '>&amp;</span>self<span style='color:#808030; '>]</span><span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span> <span style='color:#800000; font-weight:bold; '>const</span> index_constant<span style='color:#808030; '>)</span> <span style='color:#808030; '>-</span><span style='color:#808030; '>></span> decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
        <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>)</span><span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>get<span style='color:#808030; '>&lt;</span>index_constant<span style='color:#808030; '>.</span>value<span style='color:#808030; '>></span><span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Self<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>self<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>tup<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
      <span style='color:#800080; '>}</span><span style='color:#808030; '>,</span>
      <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>to_constant_tuple_index<span style='color:#808030; '>&lt;</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>remove_reference_t<span style='color:#808030; '>&lt;</span>T<span style='color:#808030; '>></span><span style='color:#808030; '>></span><span style='color:#808030; '>(</span>
        <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Self<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>self<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>index<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span>
  
  T<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> tup<span style='color:#800080; '>;</span>
  I<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> index<span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
</pre>

<h3><a id="ToConstantImplementation">std::to_constant_in_range Implementation</a></h3>
<p>The following is an example implementation of <code>std::to_constant_in_range</code>, which is used behind-the-scenes by <code>std::access_tuple</code>, <code>std::active_field_of</code>, <code>std::to_constant_discriminator</code>, and <code>std::to_constant_tuple_index</code>. Once again, this code elides conditional <code>noexcept</code> and SFINAE exploitation for brevity.</p>

<pre style='color:#000000;background:#ffffff;'><span style='color:#696969; '>// A function that invokes the provided function with</span>
<span style='color:#696969; '>// a std::integral_constant of the specified value and offset.</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> ReturnType<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> T<span style='color:#808030; '>,</span> T Value<span style='color:#808030; '>,</span> T Offset<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#800080; '>></span>
constexpr ReturnType invoke_with_constant_impl<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>)</span><span style='color:#808030; '>(</span>
      <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>integral_constant<span style='color:#808030; '>&lt;</span>T<span style='color:#808030; '>,</span> Value <span style='color:#808030; '>+</span> Offset<span style='color:#808030; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#696969; '>// Indexes into a constexpr table of function pointers</span>
<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#800080; '>></span> <span style='color:#800000; font-weight:bold; '>class</span> ReturnTypeDeducer<span style='color:#808030; '>,</span>
          <span style='color:#800000; font-weight:bold; '>class</span> T<span style='color:#808030; '>,</span> T Offset<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> I<span style='color:#808030; '>,</span> I<span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span> Indices<span style='color:#800080; '>></span>
constexpr decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> invoke_with_constant<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>,</span> T index<span style='color:#808030; '>,</span>
                                              <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>integer_sequence<span style='color:#808030; '>&lt;</span>I<span style='color:#808030; '>,</span> Indices<span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>></span><span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
  <span style='color:#696969; '>// Each invocation may potentially have a different return type, so we</span>
  <span style='color:#696969; '>// need to use the ReturnTypeDeducer to figure out what we should</span>
  <span style='color:#696969; '>// actually return.</span>
  <span style='color:#800000; font-weight:bold; '>using</span> return_type
      <span style='color:#808030; '>=</span> ReturnTypeDeducer<span style='color:#808030; '>&lt;</span>
          decltype<span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>declval<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>integral_constant<span style='color:#808030; '>&lt;</span>T<span style='color:#808030; '>,</span> Indices <span style='color:#808030; '>+</span> Offset<span style='color:#808030; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>></span><span style='color:#800080; '>;</span>

  <span style='color:#800000; font-weight:bold; '>return</span> <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span><span style='color:#603000; '>array</span><span style='color:#808030; '>&lt;</span>return_type<span style='color:#808030; '>(</span><span style='color:#808030; '>*</span><span style='color:#808030; '>)</span><span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span><span style='color:#808030; '>)</span><span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>sizeof</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>(</span>Indices<span style='color:#808030; '>)</span><span style='color:#808030; '>></span><span style='color:#800080; '>{</span>
      <span style='color:#800080; '>{</span><span style='color:#800080; '>{</span>invoke_with_constant_impl<span style='color:#800080; '>&lt;</span>return_type<span style='color:#808030; '>,</span> T<span style='color:#808030; '>,</span> Indices<span style='color:#808030; '>,</span> Offset<span style='color:#808030; '>,</span> Fun<span style='color:#800080; '>></span><span style='color:#800080; '>}</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#800080; '>}</span><span style='color:#800080; '>}</span>
      <span style='color:#808030; '>[</span>index <span style='color:#808030; '>-</span> Offset<span style='color:#808030; '>]</span><span style='color:#808030; '>(</span><span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span>

<span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> T<span style='color:#808030; '>,</span> T BeginValue<span style='color:#808030; '>,</span> T EndValue<span style='color:#800080; '>></span>
<span style='color:#800000; font-weight:bold; '>struct</span> to_constant_in_range_impl <span style='color:#800080; '>{</span>
  <span style='color:#696969; '>// Instantiations of "type" are used as the Provider</span>
  <span style='color:#696969; '>// template argument of argument_provider.</span>
  <span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span> U<span style='color:#800080; '>></span>
  <span style='color:#800000; font-weight:bold; '>struct</span> type
  <span style='color:#800080; '>{</span>    
    <span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>template</span> <span style='color:#800080; '>&lt;</span><span style='color:#800000; font-weight:bold; '>class</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#808030; '>.</span><span style='color:#800080; '>></span> <span style='color:#800000; font-weight:bold; '>class</span> ReturnTypeDeducer<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Fun<span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>class</span> Self<span style='color:#800080; '>></span>
    <span style='color:#800000; font-weight:bold; '>static</span> constexpr decltype<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>auto</span><span style='color:#808030; '>)</span> provide<span style='color:#808030; '>(</span>Fun<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> fun<span style='color:#808030; '>,</span> Self<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> self<span style='color:#808030; '>)</span> <span style='color:#800080; '>{</span>
      <span style='color:#800000; font-weight:bold; '>return</span> __detail<span style='color:#800080; '>::</span>invoke_with_constant<span style='color:#800080; '>&lt;</span>ReturnTypeDeducer<span style='color:#808030; '>,</span> T<span style='color:#808030; '>,</span> BeginValue<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>
        <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Fun<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>fun<span style='color:#808030; '>)</span><span style='color:#808030; '>,</span>
        <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>forward<span style='color:#800080; '>&lt;</span>Self<span style='color:#800080; '>></span><span style='color:#808030; '>(</span>self<span style='color:#808030; '>)</span><span style='color:#808030; '>.</span>value<span style='color:#808030; '>,</span>
        <span style='color:#666616; '>std</span><span style='color:#800080; '>::</span>make_index_sequence<span style='color:#808030; '>&lt;</span>EndValue <span style='color:#808030; '>-</span> BeginValue<span style='color:#808030; '>></span><span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
    <span style='color:#800080; '>}</span>
  
    U<span style='color:#808030; '>&amp;</span><span style='color:#808030; '>&amp;</span> value<span style='color:#800080; '>;</span>
  <span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
<span style='color:#800080; '>}</span><span style='color:#800080; '>;</span>
</pre>

<h2><a id="FurtherWork">Further Work</a></h2>
<p>The specification presented in this proposal is not yet sufficient and will require more effort if the facilities are considered useful. One notable area that needs work is a specification of the requirements of a <code>ReturnTypeDeducer</code>. It is also likely that, if accepted, argument providers should live in their own namespace so as to not conflict with functionality in the top-level <code>std</code> namespace.</p>

<h2><a id="AlternativeCustomization">Alternative Customization</a></h2>
<p>The current specification requires that all argument providers are instantiations of the <code>argument_provider</code> template. This was done for simplicity, but customization could be done equivalently with traits directly. The author of this proposal leaves the means of customization open for discussion if it is a point of contention.</p>

<h2><a id="Acknowledgments">Acknowledgments</a></h2>
<p>Thanks to Tony Van Eerd who encouraged me to write this paper, and to Michael Park who pointed out the <code>constexpr</code> table-lookup form of variant visitation to me, which is used in the example implementation of <code>std::to_constant_in_range</code>.</p>

<h2><a id="References">References</a></h2>
<p>[<a id="References_Variant">1</a>] Axel Naumann: "Variant: a type-safe union that is rarely invalid" P0088R0 <a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0088r0.pdf" target="_blank">http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0088r0.pdf</a></p>
<p>[<a id="References_PythonUnpacking">2</a>] Python Software Foundation: "The Python Tutorial" <a href="https://docs.python.org/3.5/tutorial/controlflow.html#unpacking-argument-lists" target="_blank">https://docs.python.org/3.5/tutorial/controlflow.html#unpacking-argument-lists</a></p>
<p>[<a id="References_ClayDispatchOp">3</a>] Clay Labs: "The Clay Programming Language, Language Reference" <a href="https://github.com/jckarter/clay/blob/master/doc/language-reference.md#dispatchoperator" target="_blank">https://github.com/jckarter/clay/blob/master/doc/language-reference.md#dispatchoperator</a></p>
<p>[<a id="References_BoostSwitch">4</a>] Steven Watanabe: "Boost.Switch" <a href="http://lists.boost.org/boost-announce/2008/01/0166.php" target="_blank">http://lists.boost.org/boost-announce/2008/01/0166.php</a></p>
</body></html>
