1
0
forked from boostorg/mp11

Merge branch 'develop'

This commit is contained in:
Peter Dimov
2017-03-22 02:57:06 +02:00
9 changed files with 105 additions and 54 deletions

View File

@@ -233,11 +233,11 @@
</pre> </pre>
<p> <p>
A <span class="emphasis"><em>quoted metafunction</em></span> is a class with a public metafunction A <span class="emphasis"><em>quoted metafunction</em></span> is a class with a public metafunction
called <code class="computeroutput"><span class="identifier">invoke</span></code>, for example called <code class="computeroutput"><span class="identifier">fn</span></code>, for example
</p> </p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Q1</span> <span class="special">{</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...&gt;</span> <span class="keyword">using</span> <span class="identifier">invoke</span> <span class="special">=</span> <span class="keyword">void</span><span class="special">;</span> <span class="special">};</span> <pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">Q1</span> <span class="special">{</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...&gt;</span> <span class="keyword">using</span> <span class="identifier">fn</span> <span class="special">=</span> <span class="keyword">void</span><span class="special">;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">Q2</span> <span class="special">{</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">invoke</span> <span class="special">=</span> <span class="identifier">T</span><span class="special">*;</span> <span class="special">};</span> <span class="keyword">struct</span> <span class="identifier">Q2</span> <span class="special">{</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">fn</span> <span class="special">=</span> <span class="identifier">T</span><span class="special">*;</span> <span class="special">};</span>
<span class="keyword">struct</span> <span class="identifier">Q3</span> <span class="special">{</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">invoke</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">integral_constant</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">,</span> <span class="keyword">sizeof</span><span class="special">...(</span><span class="identifier">T</span><span class="special">)&gt;;</span> <span class="special">};</span> <span class="keyword">struct</span> <span class="identifier">Q3</span> <span class="special">{</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">fn</span> <span class="special">=</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">integral_constant</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span><span class="special">,</span> <span class="keyword">sizeof</span><span class="special">...(</span><span class="identifier">T</span><span class="special">)&gt;;</span> <span class="special">};</span>
</pre> </pre>
<p> <p>
An <span class="emphasis"><em>integral constant type</em></span> is a class with a public member An <span class="emphasis"><em>integral constant type</em></span> is a class with a public member
@@ -391,7 +391,7 @@
</p> </p>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">Qret</span> <pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">Qret</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">invoke</span> <span class="special">=</span> <span class="keyword">decltype</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;()(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;()...</span> <span class="special">)</span> <span class="special">);</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">fn</span> <span class="special">=</span> <span class="keyword">decltype</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;()(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;()...</span> <span class="special">)</span> <span class="special">);</span>
<span class="special">};</span> <span class="special">};</span>
</pre> </pre>
<p> <p>
@@ -403,7 +403,7 @@
just a matter of applying it over the possible combinations of the variant just a matter of applying it over the possible combinations of the variant
values: values:
</p> </p>
<pre class="programlisting"><span class="keyword">using</span> <span class="identifier">R</span> <span class="special">=</span> <span class="identifier">mp_product</span><span class="special">&lt;</span><span class="identifier">Qret</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;::</span><span class="keyword">template</span> <span class="identifier">invoke</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference_t</span><span class="special">&lt;</span><span class="identifier">V</span><span class="special">&gt;...&gt;;</span> <pre class="programlisting"><span class="keyword">using</span> <span class="identifier">R</span> <span class="special">=</span> <span class="identifier">mp_product</span><span class="special">&lt;</span><span class="identifier">Qret</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;::</span><span class="keyword">template</span> <span class="identifier">fn</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference_t</span><span class="special">&lt;</span><span class="identifier">V</span><span class="special">&gt;...&gt;;</span>
</pre> </pre>
<p> <p>
Why does this work? <code class="computeroutput"><span class="identifier">mp_product</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">,</span> Why does this work? <code class="computeroutput"><span class="identifier">mp_product</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">,</span>
@@ -422,7 +422,7 @@
either <code class="computeroutput"><span class="keyword">int</span></code> or <code class="computeroutput"><span class="keyword">float</span></code>, and we need to filter out the duplicates. either <code class="computeroutput"><span class="keyword">int</span></code> or <code class="computeroutput"><span class="keyword">float</span></code>, and we need to filter out the duplicates.
So, So,
</p> </p>
<pre class="programlisting"><span class="keyword">using</span> <span class="identifier">R</span> <span class="special">=</span> <span class="identifier">mp_unique</span><span class="special">&lt;</span><span class="identifier">mp_product</span><span class="special">&lt;</span><span class="identifier">Qret</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;::</span><span class="keyword">template</span> <span class="identifier">invoke</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference_t</span><span class="special">&lt;</span><span class="identifier">V</span><span class="special">&gt;...&gt;&gt;;</span> <pre class="programlisting"><span class="keyword">using</span> <span class="identifier">R</span> <span class="special">=</span> <span class="identifier">mp_unique</span><span class="special">&lt;</span><span class="identifier">mp_product</span><span class="special">&lt;</span><span class="identifier">Qret</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;::</span><span class="keyword">template</span> <span class="identifier">fn</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference_t</span><span class="special">&lt;</span><span class="identifier">V</span><span class="special">&gt;...&gt;&gt;;</span>
</pre> </pre>
<p> <p>
and we're done: and we're done:
@@ -438,12 +438,12 @@
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">Qret</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">Qret</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">invoke</span> <span class="special">=</span> <span class="keyword">decltype</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;()(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;()...</span> <span class="special">)</span> <span class="special">);</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">fn</span> <span class="special">=</span> <span class="keyword">decltype</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;()(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">declval</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">&gt;()...</span> <span class="special">)</span> <span class="special">);</span>
<span class="special">};</span> <span class="special">};</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">V</span><span class="special">&gt;</span> <span class="keyword">auto</span> <span class="identifier">rvisit</span><span class="special">(</span> <span class="identifier">F</span><span class="special">&amp;&amp;</span> <span class="identifier">f</span><span class="special">,</span> <span class="identifier">V</span><span class="special">&amp;&amp;...</span> <span class="identifier">v</span> <span class="special">)</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">F</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">V</span><span class="special">&gt;</span> <span class="keyword">auto</span> <span class="identifier">rvisit</span><span class="special">(</span> <span class="identifier">F</span><span class="special">&amp;&amp;</span> <span class="identifier">f</span><span class="special">,</span> <span class="identifier">V</span><span class="special">&amp;&amp;...</span> <span class="identifier">v</span> <span class="special">)</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">using</span> <span class="identifier">R</span> <span class="special">=</span> <span class="identifier">mp_unique</span><span class="special">&lt;</span><span class="identifier">mp_product</span><span class="special">&lt;</span><span class="identifier">Qret</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;::</span><span class="keyword">template</span> <span class="identifier">invoke</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference_t</span><span class="special">&lt;</span><span class="identifier">V</span><span class="special">&gt;...&gt;&gt;;</span> <span class="keyword">using</span> <span class="identifier">R</span> <span class="special">=</span> <span class="identifier">mp_unique</span><span class="special">&lt;</span><span class="identifier">mp_product</span><span class="special">&lt;</span><span class="identifier">Qret</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;::</span><span class="keyword">template</span> <span class="identifier">fn</span><span class="special">,</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">remove_reference_t</span><span class="special">&lt;</span><span class="identifier">V</span><span class="special">&gt;...&gt;&gt;;</span>
<span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">visit</span><span class="special">(</span> <span class="special">[&amp;](</span> <span class="keyword">auto</span><span class="special">&amp;&amp;...</span> <span class="identifier">x</span> <span class="special">){</span> <span class="keyword">return</span> <span class="identifier">R</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;(</span><span class="identifier">f</span><span class="special">)(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">x</span><span class="special">)&gt;(</span><span class="identifier">x</span><span class="special">)...</span> <span class="special">)</span> <span class="special">);</span> <span class="special">},</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">V</span><span class="special">&gt;(</span> <span class="identifier">v</span> <span class="special">)...</span> <span class="special">);</span> <span class="keyword">return</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">visit</span><span class="special">(</span> <span class="special">[&amp;](</span> <span class="keyword">auto</span><span class="special">&amp;&amp;...</span> <span class="identifier">x</span> <span class="special">){</span> <span class="keyword">return</span> <span class="identifier">R</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;(</span><span class="identifier">f</span><span class="special">)(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="keyword">decltype</span><span class="special">(</span><span class="identifier">x</span><span class="special">)&gt;(</span><span class="identifier">x</span><span class="special">)...</span> <span class="special">)</span> <span class="special">);</span> <span class="special">},</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span><span class="identifier">V</span><span class="special">&gt;(</span> <span class="identifier">v</span> <span class="special">)...</span> <span class="special">);</span>
<span class="special">}</span> <span class="special">}</span>
@@ -880,14 +880,14 @@
</h4></div></div></div> </h4></div></div></div>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...&gt;</span> <span class="keyword">class</span> <span class="identifier">F</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">mp_quote</span> <pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...&gt;</span> <span class="keyword">class</span> <span class="identifier">F</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">struct</span> <span class="identifier">mp_quote</span>
<span class="special">{</span> <span class="special">{</span>
<span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">invoke</span> <span class="special">=</span> <span class="identifier">F</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...,</span> <span class="identifier">U</span><span class="special">...&gt;;</span> <span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span><span class="special">...</span> <span class="identifier">U</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">fn</span> <span class="special">=</span> <span class="identifier">F</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...,</span> <span class="identifier">U</span><span class="special">...&gt;;</span>
<span class="special">};</span> <span class="special">};</span>
</pre> </pre>
<p> <p>
<code class="computeroutput"><span class="identifier">mp_quote</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">,</span> <span class="identifier">T</span><span class="special">...&gt;</span></code> transforms the template <code class="computeroutput"><span class="identifier">F</span></code> into a type. In the common case <code class="computeroutput"><span class="identifier">mp_quote</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;</span></code>, <code class="computeroutput"><span class="identifier">mp_quote</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">,</span> <span class="identifier">T</span><span class="special">...&gt;</span></code> transforms the template <code class="computeroutput"><span class="identifier">F</span></code> into a type. In the common case <code class="computeroutput"><span class="identifier">mp_quote</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;</span></code>,
the nested template <code class="computeroutput"><span class="identifier">invoke</span></code> the nested template <code class="computeroutput"><span class="identifier">fn</span></code>
of the result is an alias for <code class="computeroutput"><span class="identifier">F</span></code>; of the result is an alias for <code class="computeroutput"><span class="identifier">F</span></code>;
otherwise, <code class="computeroutput"><span class="identifier">invoke</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">...&gt;</span></code> otherwise, <code class="computeroutput"><span class="identifier">fn</span><span class="special">&lt;</span><span class="identifier">U</span><span class="special">...&gt;</span></code>
is an alias for <code class="computeroutput"><span class="identifier">F</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...,</span> <span class="identifier">U</span><span class="special">...&gt;</span></code>, is an alias for <code class="computeroutput"><span class="identifier">F</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...,</span> <span class="identifier">U</span><span class="special">...&gt;</span></code>,
allowing partial application. allowing partial application.
</p> </p>
@@ -896,10 +896,10 @@
<div class="titlepage"><div><div><h4 class="title"> <div class="titlepage"><div><div><h4 class="title">
<a name="mp11.reference.utility.mp_invoke_q_t"></a><a class="link" href="mp11.html#mp11.reference.utility.mp_invoke_q_t" title="mp_invoke&lt;Q, T...&gt;"><code class="computeroutput"><span class="identifier">mp_invoke</span><span class="special">&lt;</span><span class="identifier">Q</span><span class="special">,</span> <span class="identifier">T</span><span class="special">...&gt;</span></code></a> <a name="mp11.reference.utility.mp_invoke_q_t"></a><a class="link" href="mp11.html#mp11.reference.utility.mp_invoke_q_t" title="mp_invoke&lt;Q, T...&gt;"><code class="computeroutput"><span class="identifier">mp_invoke</span><span class="special">&lt;</span><span class="identifier">Q</span><span class="special">,</span> <span class="identifier">T</span><span class="special">...&gt;</span></code></a>
</h4></div></div></div> </h4></div></div></div>
<pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Q</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">mp_invoke</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">Q</span><span class="special">::</span><span class="keyword">template</span> <span class="identifier">invoke</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...&gt;;</span> <pre class="programlisting"><span class="keyword">template</span><span class="special">&lt;</span><span class="keyword">class</span> <span class="identifier">Q</span><span class="special">,</span> <span class="keyword">class</span><span class="special">...</span> <span class="identifier">T</span><span class="special">&gt;</span> <span class="keyword">using</span> <span class="identifier">mp_invoke</span> <span class="special">=</span> <span class="keyword">typename</span> <span class="identifier">Q</span><span class="special">::</span><span class="keyword">template</span> <span class="identifier">fn</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...&gt;;</span>
</pre> </pre>
<p> <p>
<code class="computeroutput"><span class="identifier">mp_invoke</span><span class="special">&lt;</span><span class="identifier">Q</span><span class="special">,</span> <span class="identifier">T</span><span class="special">...&gt;</span></code> evaluates the nested template <code class="computeroutput"><span class="identifier">invoke</span></code> of a quoted metafunction. <code class="computeroutput"><span class="identifier">mp_invoke</span><span class="special">&lt;</span><span class="identifier">mp_quote</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;,</span> <span class="identifier">T</span><span class="special">...&gt;</span></code> <code class="computeroutput"><span class="identifier">mp_invoke</span><span class="special">&lt;</span><span class="identifier">Q</span><span class="special">,</span> <span class="identifier">T</span><span class="special">...&gt;</span></code> evaluates the nested template <code class="computeroutput"><span class="identifier">fn</span></code> of a quoted metafunction. <code class="computeroutput"><span class="identifier">mp_invoke</span><span class="special">&lt;</span><span class="identifier">mp_quote</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">&gt;,</span> <span class="identifier">T</span><span class="special">...&gt;</span></code>
is an alias for <code class="computeroutput"><span class="identifier">F</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...&gt;</span></code>. is an alias for <code class="computeroutput"><span class="identifier">F</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...&gt;</span></code>.
<code class="computeroutput"><span class="identifier">mp_invoke</span><span class="special">&lt;</span><span class="identifier">mp_quote</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">,</span> <span class="identifier">T</span><span class="special">...&gt;,</span> <span class="identifier">U</span><span class="special">...&gt;</span></code> is an alias for <code class="computeroutput"><span class="identifier">F</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...,</span> <span class="identifier">U</span><span class="special">...&gt;</span></code>. <code class="computeroutput"><span class="identifier">mp_invoke</span><span class="special">&lt;</span><span class="identifier">mp_quote</span><span class="special">&lt;</span><span class="identifier">F</span><span class="special">,</span> <span class="identifier">T</span><span class="special">...&gt;,</span> <span class="identifier">U</span><span class="special">...&gt;</span></code> is an alias for <code class="computeroutput"><span class="identifier">F</span><span class="special">&lt;</span><span class="identifier">T</span><span class="special">...,</span> <span class="identifier">U</span><span class="special">...&gt;</span></code>.
</p> </p>
@@ -1688,7 +1688,7 @@
</div> </div>
</div> </div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr> <table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"><p><small>Last revised: March 18, 2017 at 18:33:25 GMT</small></p></td> <td align="left"><p><small>Last revised: March 20, 2017 at 14:09:13 GMT</small></p></td>
<td align="right"><div class="copyright-footer"></div></td> <td align="right"><div class="copyright-footer"></div></td>
</tr></table> </tr></table>
<hr> <hr>

View File

@@ -18,11 +18,11 @@ A /metafunction/ is a class template or a template alias whose parameters are al
template<class T> using F2 = T*; template<class T> using F2 = T*;
template<class... T> using F3 = std::integral_constant<std::size_t, sizeof...(T)>; template<class... T> using F3 = std::integral_constant<std::size_t, sizeof...(T)>;
A /quoted metafunction/ is a class with a public metafunction called `invoke`, for example A /quoted metafunction/ is a class with a public metafunction called `fn`, for example
struct Q1 { template<class...> using invoke = void; }; struct Q1 { template<class...> using fn = void; };
struct Q2 { template<class T> using invoke = T*; }; struct Q2 { template<class T> using fn = T*; };
struct Q3 { template<class... T> using invoke = std::integral_constant<std::size_t, sizeof...(T)>; }; struct Q3 { template<class... T> using fn = std::integral_constant<std::size_t, sizeof...(T)>; };
An /integral constant type/ is a class with a public member `value` that is an integral constant in the C++ sense. For example, An /integral constant type/ is a class with a public member `value` that is an integral constant in the C++ sense. For example,
`std::integral_constant<int, 7>`, or `std::integral_constant<int, 7>`, or

View File

@@ -107,14 +107,14 @@ We'll first define a helper quoted metafunction `Qret<F>` that returns the resul
template<class F> struct Qret template<class F> struct Qret
{ {
template<class... T> using invoke = decltype( std::declval<F>()( std::declval<T>()... ) ); template<class... T> using fn = decltype( std::declval<F>()( std::declval<T>()... ) );
}; };
(Unfortunately, we can't just define this metafunction inside `rvisit`; the language prohibits defining template aliases inside functions.) (Unfortunately, we can't just define this metafunction inside `rvisit`; the language prohibits defining template aliases inside functions.)
With `Qret` in hand, a `variant` of the possible return types is just a matter of applying it over the possible combinations of the variant values: With `Qret` in hand, a `variant` of the possible return types is just a matter of applying it over the possible combinations of the variant values:
using R = mp_product<Qret<F>::template invoke, std::remove_reference_t<V>...>; using R = mp_product<Qret<F>::template fn, std::remove_reference_t<V>...>;
Why does this work? `mp_product<F, L1<T1...>, L2<T2...>, ..., Ln<Tn...>>` returns `L1<F<U1, U2, ..., Un>, ...>`, where `Ui` traverse all Why does this work? `mp_product<F, L1<T1...>, L2<T2...>, ..., Ln<Tn...>>` returns `L1<F<U1, U2, ..., Un>, ...>`, where `Ui` traverse all
possible combinations of list values. Since in our case all `Li` are `std::variant`, the result will also be `std::variant`. possible combinations of list values. Since in our case all `Li` are `std::variant`, the result will also be `std::variant`.
@@ -123,7 +123,7 @@ One more step remains. Suppose that, as above, we're passing two variants of typ
`[]( auto const& x, auto const& y ){ return x + y; }`. This will generate `R` of length 9, one per each combination, but many of those `[]( auto const& x, auto const& y ){ return x + y; }`. This will generate `R` of length 9, one per each combination, but many of those
elements will be the same, either `int` or `float`, and we need to filter out the duplicates. So, elements will be the same, either `int` or `float`, and we need to filter out the duplicates. So,
using R = mp_unique<mp_product<Qret<F>::template invoke, std::remove_reference_t<V>...>>; using R = mp_unique<mp_product<Qret<F>::template fn, std::remove_reference_t<V>...>>;
and we're done: and we're done:
@@ -138,12 +138,12 @@ and we're done:
template<class F> struct Qret template<class F> struct Qret
{ {
template<class... T> using invoke = decltype( std::declval<F>()( std::declval<T>()... ) ); template<class... T> using fn = decltype( std::declval<F>()( std::declval<T>()... ) );
}; };
template<class F, class... V> auto rvisit( F&& f, V&&... v ) template<class F, class... V> auto rvisit( F&& f, V&&... v )
{ {
using R = mp_unique<mp_product<Qret<F>::template invoke, std::remove_reference_t<V>...>>; using R = mp_unique<mp_product<Qret<F>::template fn, std::remove_reference_t<V>...>>;
return std::visit( [&]( auto&&... x ){ return R( std::forward<F>(f)( std::forward<decltype(x)>(x)... ) ); }, std::forward<V>( v )... ); return std::visit( [&]( auto&&... x ){ return R( std::forward<F>(f)( std::forward<decltype(x)>(x)... ) ); }, std::forward<V>( v )... );
} }

View File

@@ -64,17 +64,17 @@ When `mp_valid<F, T...>` is `mp_true`, `mp_defer<F, T...>` is a struct with a ne
[section `mp_quote<F, T...>`] [section `mp_quote<F, T...>`]
template<template<class...> class F, class... T> struct mp_quote template<template<class...> class F, class... T> struct mp_quote
{ {
template<class... U> using invoke = F<T..., U...>; template<class... U> using fn = F<T..., U...>;
}; };
`mp_quote<F, T...>` transforms the template `F` into a type. In the common case `mp_quote<F>`, the nested template `invoke` of the result is an alias for `F`; `mp_quote<F, T...>` transforms the template `F` into a type. In the common case `mp_quote<F>`, the nested template `fn` of the result is an alias for `F`;
otherwise, `invoke<U...>` is an alias for `F<T..., U...>`, allowing partial application. otherwise, `fn<U...>` is an alias for `F<T..., U...>`, allowing partial application.
[endsect] [endsect]
[section `mp_invoke<Q, T...>`] [section `mp_invoke<Q, T...>`]
template<class Q, class... T> using mp_invoke = typename Q::template invoke<T...>; template<class Q, class... T> using mp_invoke = typename Q::template fn<T...>;
`mp_invoke<Q, T...>` evaluates the nested template `invoke` of a quoted metafunction. `mp_invoke<mp_quote<F>, T...>` is an alias for `F<T...>`. `mp_invoke<mp_quote<F, T...>, U...>` is an alias for `F<T..., U...>`. `mp_invoke<Q, T...>` evaluates the nested template `fn` of a quoted metafunction. `mp_invoke<mp_quote<F>, T...>` is an alias for `F<T...>`. `mp_invoke<mp_quote<F, T...>, U...>` is an alias for `F<T..., U...>`.
[endsect] [endsect]
[endsect] [endsect]

View File

@@ -290,23 +290,47 @@ template<class L, class I> using mp_at = typename detail::mp_at_impl<L, I>::type
namespace detail namespace detail
{ {
template<class L, std::size_t N, class E = void> struct mp_take_c_impl;
template<template<class...> class L, class... T> struct mp_take_c_impl<L<T...>, 0>
{
using type = L<>;
};
template<template<class...> class L, class T1, class... T> struct mp_take_c_impl<L<T1, T...>, 1>
{
using type = L<T1>;
};
template<template<class...> class L, class T1, class T2, class... T> struct mp_take_c_impl<L<T1, T2, T...>, 2>
{
using type = L<T1, T2>;
};
template<template<class...> class L, class T1, class T2, class T3, class... T> struct mp_take_c_impl<L<T1, T2, T3, T...>, 3>
{
using type = L<T1, T2, T3>;
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class... T> struct mp_take_c_impl<L<T1, T2, T3, T4, T...>, 4>
{
using type = L<T1, T2, T3, T4>;
};
template<template<class...> class L, class T1, class T2, class T3, class T4, class T5, class... T, std::size_t N> struct mp_take_c_impl<L<T1, T2, T3, T4, T5, T...>, N, typename std::enable_if<N >= 5>::type>
{
using type = mp_append<L<T1, T2, T3, T4, T5>, typename mp_take_c_impl<L<T...>, N-5>::type>;
};
template<class L, class N> struct mp_take_impl template<class L, class N> struct mp_take_impl
{ {
static_assert( N::value >= 0, "mp_take<L, N>: N must not be negative" ); static_assert( N::value >= 0, "mp_take<L, N>: N must not be negative" );
using type = typename mp_take_c_impl<L, N::value>::type;
using _map = mp_transform<mp_list, mp_iota<mp_size<L>>, L>;
template<class I> using _f = mp_second<mp_map_find<_map, I>>;
using _ind = mp_iota_c<N::value>;
using type = mp_assign<L, mp_transform<_f, _ind>>;
}; };
} // namespace detail } // namespace detail
template<class L, std::size_t N> using mp_take_c = typename detail::mp_take_impl<L, mp_size_t<N>>::type; template<class L, std::size_t N> using mp_take_c = typename detail::mp_take_c_impl<L, N>::type;
template<class L, class N> using mp_take = typename detail::mp_take_impl<L, N>::type; template<class L, class N> using mp_take = typename detail::mp_take_impl<L, N>::type;
// mp_replace<L, V, W> // mp_replace<L, V, W>

View File

@@ -106,7 +106,16 @@ template<template<class...> class F, class... T> using mp_defer = mp_if<mp_valid
// mp_quote // mp_quote
template<template<class...> class F, class... T> struct mp_quote template<template<class...> class F, class... T> struct mp_quote
{ {
template<class... U> using invoke = F<T..., U...>; private:
template<class... U> struct _fn { using type = F<T..., U...>; };
public:
// the indirection through _fn works around the language inability
// to expand T.. to expand into a fixed parameter list of an alias template
template<class... U> using fn = typename _fn<U...>::type;
}; };
// mp_unquote // mp_unquote
@@ -115,7 +124,7 @@ namespace detail
template<class Q, class... T> struct mp_invoke_impl template<class Q, class... T> struct mp_invoke_impl
{ {
using type = typename Q::template invoke<T...>; using type = typename Q::template fn<T...>;
}; };
template<template<class...> class F, class... T, class... U> struct mp_invoke_impl<mp_quote<F, T...>, U...> template<template<class...> class F, class... T, class... U> struct mp_invoke_impl<mp_quote<F, T...>, U...>

View File

@@ -17,22 +17,27 @@ using boost::mp11::mp_size_t;
struct Q1 struct Q1
{ {
template<class...> using invoke = void; template<class...> using fn = void;
}; };
struct Q2 struct Q2
{ {
template<class...> class invoke; template<class...> class fn;
}; };
struct Q3 struct Q3
{ {
template<class... T> using invoke = mp_size_t<sizeof...(T)>; template<class... T> using fn = mp_size_t<sizeof...(T)>;
}; };
struct Q4 struct Q4
{ {
template<class T1, class... T> using invoke = T1; template<class T1, class... T> using fn = T1;
};
struct Q5
{
template<class T1, class T2> using fn = T2;
}; };
int main() int main()
@@ -41,9 +46,9 @@ int main()
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q1, int>, void>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q1, int>, void>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q1, int[], char[]>, void>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q1, int[], char[]>, void>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q2>, Q2::invoke<>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q2>, Q2::fn<>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q2, int>, Q2::invoke<int>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q2, int>, Q2::fn<int>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q2, int[], char[]>, Q2::invoke<int[], char[]>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q2, int[], char[]>, Q2::fn<int[], char[]>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q3>, mp_size_t<0>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q3>, mp_size_t<0>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q3, int>, mp_size_t<1>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q3, int>, mp_size_t<1>>));
@@ -52,5 +57,7 @@ int main()
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q4, int>, int>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q4, int>, int>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q4, int[], char[]>, int[]>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q4, int[], char[]>, int[]>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_invoke<Q5, int, float>, float>));
return boost::report_errors(); return boost::report_errors();
} }

View File

@@ -24,7 +24,7 @@ struct D1: B {};
struct D2: B {}; struct D2: B {};
struct ND {}; struct ND {};
template<class... T> using is_base_of_t = typename std::is_base_of<T...>::type; template<class T, class U> using is_base_of_t = typename std::is_base_of<T, U>::type;
int main() int main()
{ {
@@ -54,10 +54,11 @@ int main()
{ {
using Q = mp_quote<mp_identity_t>; using Q = mp_quote<mp_identity_t>;
// using R1 = Y<Q::template invoke, void, char, int>; #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
// BOOST_TEST_TRAIT_TRUE((std::is_same<R1, X<void, char, int>>)); #else
// using R1 = Y<Q::fn, void, char, int>;
// error: pack expansion used as argument for non-pack parameter of alias template BOOST_TEST_TRAIT_TRUE((std::is_same<R1, X<void, char, int>>));
#endif
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 && BOOST_MSVC >= 1900 ) #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1910 && BOOST_MSVC >= 1900 )
#else #else
@@ -71,7 +72,7 @@ int main()
#if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 ) #if defined( BOOST_MSVC ) && BOOST_WORKAROUND( BOOST_MSVC, <= 1800 )
#else #else
using R1 = Y<Q::template invoke, D1, D2, ND, int>; using R1 = Y<Q::fn, D1, D2, ND, int>;
BOOST_TEST_TRAIT_TRUE((std::is_same<R1, X<std::true_type, std::true_type, std::false_type, std::false_type>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<R1, X<std::true_type, std::true_type, std::false_type, std::false_type>>));
#endif #endif

View File

@@ -49,6 +49,11 @@ int main()
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<3>>, mp_list<X1, X2, X3>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<3>>, mp_list<X1, X2, X3>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<4>>, mp_list<X1, X2, X3, X4>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<4>>, mp_list<X1, X2, X3, X4>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<5>>, mp_list<X1, X2, X3, X4, X5>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<5>>, mp_list<X1, X2, X3, X4, X5>>));
using L3 = mp_list<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>;
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L3, 8>, mp_list<X1, X2, X3, X4, X5, X1, X2, X3>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L3, mp_size_t<9>>, mp_list<X1, X2, X3, X4, X5, X1, X2, X3, X4>>));
} }
{ {
@@ -72,6 +77,11 @@ int main()
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<3>>, std::tuple<X1, X2, X3>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<3>>, std::tuple<X1, X2, X3>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<4>>, std::tuple<X1, X2, X3, X4>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<4>>, std::tuple<X1, X2, X3, X4>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<5>>, std::tuple<X1, X2, X3, X4, X5>>)); BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L2, mp_size_t<5>>, std::tuple<X1, X2, X3, X4, X5>>));
using L3 = std::tuple<X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5, X1, X2, X3, X4, X5>;
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take_c<L3, 8>, std::tuple<X1, X2, X3, X4, X5, X1, X2, X3>>));
BOOST_TEST_TRAIT_TRUE((std::is_same<mp_take<L3, mp_size_t<9>>, std::tuple<X1, X2, X3, X4, X5, X1, X2, X3, X4>>));
} }
{ {