Note that there are some explanatory texts on larger screens.

plurals
  1. POHow can one make a variadic-based chained-indexing function?
    primarykey
    data
    text
    <p>If I have an object <code>a</code> that either a built-in array or a class-type with a suitable <code>operator []</code>, and its returned type can be indexed itself, how should I write a generic function that can index all of them with a variadic call instead of separated bracket block? In other words, I can make expressions like:</p> <pre><code>a[i0][i1]...[iK] </code></pre> <p>and I want to be able to write it as a single function:</p> <pre><code>slice( a, i0, i1, ..., iK ) </code></pre> <p>since the rules of C++ require <code>operator []</code> to work on single arguments, making it less-compatible with variadic stuff. (This question is based on a Usenet thread where I tried asking something similar; ending up solving only possibly-nested built-in arrays myself.)</p> <p>A first stab:</p> <pre><code>template &lt; typename T, typename U &gt; constexpr auto slice( T &amp;&amp;t, U &amp;&amp;u ) noexcept(???) -&gt; ??? { return ce_forward&lt;T&gt;(t)[ ce_forward&lt;U&gt;(u) ]; } template &lt; typename T, typename U, typename V, typename ...W &gt; constexpr auto slice( T &amp;&amp;t, U &amp;&amp;u, V &amp;&amp;v, W... &amp;&amp;w ) noexcept(???) -&gt; ??? { return slice( ce_forward&lt;T&gt;(t)[ce_forward&lt;U&gt;(u)], ce_forward&lt;V&gt;(v), ce_forward&lt;W&gt;(w)... ); } </code></pre> <p>The <code>ce_forward</code> function templates are a <code>constexpr</code>-marked <code>std::forward</code>. (Some things in the standard that could be marked <code>constexpr</code> aren't.) I'm trying to figure out the right stuff to put in the return type and exception specification spots. Some cases and caveats I know of are:</p> <ul> <li>The built-in <code>operator []</code> requires one operand to be a data-pointer (or decayed array reference) and the other to be an enumeration or integer type. The operands can be in either order. I don't know if an operand could be replaced with a class-type with an unambiguous (non-explicit?) conversion to an appropriate type.</li> <li>A class type can define <code>operator []</code> as non-static member function(s). Any such function can only have one parameter (besides <code>this</code>).</li> <li>The built-in operator can't throw. (Unless operands could be based on an UDT conversion; said conversion is the only possible throw point.) The undefined behavior caused by boundary errors is beyond our purview here.</li> <li>Whether the last indexing call returns a l-value reference, r-value reference, or value should be reflected in the return type of <code>slice</code>.</li> <li>If the (final?) call is by-value, then <code>std::is_nothrow_move_constructible&lt;ReturnType&gt;::value</code> should be OR'd to the exception specification. (By-reference returns are <code>noexcept</code>.)</li> <li>If the built-in operator involves an array, the returned reference for that step should be a r-value reference if the array is one too. (This is kind-of a defect because pointers, unlike arrays, lose their target's l- vs. r-value status, so the traditional return would always be a l-value reference.)</li> <li>For class-type indexing operators, make sure the exception-spec and return-type sections refer to the same overload (if more than one) that the function body uses. Be wary for overloads that differ only in the qualification of <code>this</code> (<code>const</code>/<code>volatile</code>/both/neither and/or <code>&amp;</code>/<code>&amp;&amp;</code>/neither).</li> </ul>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload