Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>While saying "the compiler can reserve", why rely on it? And what about automatic detection of move semantics? And what about all that repeating of the container name with the <code>begin</code>s and <code>end</code>s?</p> <p>Wouldn't you want something, you know, simpler?</p> <p>(Scroll down to <code>main</code> for the punchline)</p> <pre><code>#include &lt;type_traits&gt; #include &lt;vector&gt; #include &lt;iterator&gt; #include &lt;iostream&gt; template&lt;typename C,typename=void&gt; struct can_reserve: std::false_type {}; template&lt;typename T, typename A&gt; struct can_reserve&lt;std::vector&lt;T,A&gt;,void&gt;: std::true_type {}; template&lt;int n&gt; struct secret_enum { enum class type {}; }; template&lt;int n&gt; using SecretEnum = typename secret_enum&lt;n&gt;::type; template&lt;bool b, int override_num=1&gt; using EnableFuncIf = typename std::enable_if&lt; b, SecretEnum&lt;override_num&gt; &gt;::type; template&lt;bool b, int override_num=1&gt; using DisableFuncIf = EnableFuncIf&lt; !b, -override_num &gt;; template&lt;typename C, EnableFuncIf&lt; can_reserve&lt;C&gt;::value &gt;... &gt; void try_reserve( C&amp; c, std::size_t n ) { c.reserve(n); } template&lt;typename C, DisableFuncIf&lt; can_reserve&lt;C&gt;::value &gt;... &gt; void try_reserve( C&amp; c, std::size_t ) { } // do nothing template&lt;typename C,typename=void&gt; struct has_size_method:std::false_type {}; template&lt;typename C&gt; struct has_size_method&lt;C, typename std::enable_if&lt;std::is_same&lt; decltype( std::declval&lt;C&gt;().size() ), decltype( std::declval&lt;C&gt;().size() ) &gt;::value&gt;::type&gt;:std::true_type {}; namespace adl_aux { using std::begin; using std::end; template&lt;typename C&gt; auto adl_begin(C&amp;&amp;c)-&gt;decltype( begin(std::forward&lt;C&gt;(c)) ); template&lt;typename C&gt; auto adl_end(C&amp;&amp;c)-&gt;decltype( end(std::forward&lt;C&gt;(c)) ); } template&lt;typename C&gt; struct iterable_traits { typedef decltype( adl_aux::adl_begin(std::declval&lt;C&amp;&gt;()) ) iterator; typedef decltype( adl_aux::adl_begin(std::declval&lt;C const&amp;&gt;()) ) const_iterator; }; template&lt;typename C&gt; using Iterator = typename iterable_traits&lt;C&gt;::iterator; template&lt;typename C&gt; using ConstIterator = typename iterable_traits&lt;C&gt;::const_iterator; template&lt;typename I&gt; using IteratorCategory = typename std::iterator_traits&lt;I&gt;::iterator_category; template&lt;typename C, EnableFuncIf&lt; has_size_method&lt;C&gt;::value, 1&gt;... &gt; std::size_t size_at_least( C&amp;&amp; c ) { return c.size(); } template&lt;typename C, EnableFuncIf&lt; !has_size_method&lt;C&gt;::value &amp;&amp; std::is_base_of&lt; std::random_access_iterator_tag, IteratorCategory&lt;Iterator&lt;C&gt;&gt; &gt;::value, 2&gt;... &gt; std::size_t size_at_least( C&amp;&amp; c ) { using std::begin; using std::end; return end(c)-begin(c); }; template&lt;typename C, EnableFuncIf&lt; !has_size_method&lt;C&gt;::value &amp;&amp; !std::is_base_of&lt; std::random_access_iterator_tag, IteratorCategory&lt;Iterator&lt;C&gt;&gt; &gt;::value, 3&gt;... &gt; std::size_t size_at_least( C&amp;&amp; c ) { return 0; }; template &lt; typename It &gt; auto try_make_move_iterator(It i, std::true_type) -&gt; decltype(make_move_iterator(i)) { return make_move_iterator(i); } template &lt; typename It &gt; It try_make_move_iterator(It i, ...) { return i; } #include &lt;iostream&gt; template&lt;typename C1, typename C2&gt; C1&amp;&amp; append_containers( C1&amp;&amp; c1, C2&amp;&amp; c2 ) { using std::begin; using std::end; try_reserve( c1, size_at_least(c1) + size_at_least(c2) ); using is_rvref = std::is_rvalue_reference&lt;C2&amp;&amp;&gt;; c1.insert( end(c1), try_make_move_iterator(begin(c2), is_rvref{}), try_make_move_iterator(end(c2), is_rvref{}) ); return std::forward&lt;C1&gt;(c1); } struct append_infix_op {} append; template&lt;typename LHS&gt; struct append_on_right_op { LHS lhs; template&lt;typename RHS&gt; LHS&amp;&amp; operator=( RHS&amp;&amp; rhs ) { return append_containers( std::forward&lt;LHS&gt;(lhs), std::forward&lt;RHS&gt;(rhs) ); } }; template&lt;typename LHS&gt; append_on_right_op&lt;LHS&gt; operator+( LHS&amp;&amp; lhs, append_infix_op ) { return { std::forward&lt;LHS&gt;(lhs) }; } template&lt;typename LHS,typename RHS&gt; typename std::remove_reference&lt;LHS&gt;::type operator+( append_on_right_op&lt;LHS&gt;&amp;&amp; lhs, RHS&amp;&amp; rhs ) { typename std::decay&lt;LHS&gt;::type retval = std::forward&lt;LHS&gt;(lhs.lhs); return append_containers( std::move(retval), std::forward&lt;RHS&gt;(rhs) ); } template&lt;typename C&gt; void print_container( C&amp;&amp; c ) { for( auto&amp;&amp; x:c ) std::cout &lt;&lt; x &lt;&lt; ","; std::cout &lt;&lt; "\n"; }; int main() { std::vector&lt;int&gt; a = {0,1,2}; std::vector&lt;int&gt; b = {3,4,5}; print_container(a); print_container(b); a +append= b; const int arr[] = {6,7,8}; a +append= arr; print_container(a); print_container(b); std::vector&lt;double&gt; d = ( std::vector&lt;double&gt;{-3.14, -2, -1} +append= a ); print_container(d); std::vector&lt;double&gt; c = std::move(d) +append+ a; print_container(c); print_container(d); std::vector&lt;double&gt; e = c +append+ std::move(a); print_container(e); print_container(a); } </code></pre> <p><a href="https://ideone.com/WDBRF5">hehe</a>.</p> <p>Now with move-data-from-rhs, append-array-to-container, append forward_list-to-container, move-container-from-lhs, thanks to @DyP's help.</p> <p>Note that the above does not compile in clang thanks to the <code>EnableFunctionIf&lt;&gt;...</code> technique. In clang <a href="http://coliru.stacked-crooked.com/view?id=2aed6b92fe683bdc51dcb77e1fffdf60-bb452bed83d06e87c370fcabced7e96d">this workaround</a> works.</p>
    singulars
    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.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      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