Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Here is the corrected version of Paul Preney's code. I have informed the author by email and in comments; I have written an edit, but it has been rejected by unqualified reviewers.</p> <p>The error in the original code is that BinaryOp template parameter of math_vector_expr::operator+ is fixed.</p> <pre><code>#include &lt;array&gt; #include &lt;algorithm&gt; #include &lt;initializer_list&gt; #include &lt;type_traits&gt; #include &lt;iostream&gt; //#define DONT_USE_EXPR_TEMPL //=========================================================================== template &lt;std::size_t N&gt; class math_vector; template &lt;typename T&gt; struct plus_op; template &lt; typename LeftExpr, typename BinaryOp, typename RightExpr &gt; class math_vector_expr { public: typedef typename std::remove_reference&lt;LeftExpr&gt;::type::value_type value_type; math_vector_expr() = delete; math_vector_expr(LeftExpr l, RightExpr r) : l_(std::forward&lt;LeftExpr&gt;(l)), r_(std::forward&lt;RightExpr&gt;(r)) { } // Prohibit copying... math_vector_expr(math_vector_expr const&amp;) = delete; math_vector_expr&amp; operator =(math_vector_expr const&amp;) = delete; // Allow moves... math_vector_expr(math_vector_expr&amp;&amp;) = default; math_vector_expr&amp; operator =(math_vector_expr&amp;&amp;) = default; template &lt;typename RE&gt; auto operator +(RE&amp;&amp; re) const -&gt; math_vector_expr&lt; math_vector_expr&lt;LeftExpr,BinaryOp,RightExpr&gt; const&amp;, plus_op&lt;value_type&gt;, decltype(std::forward&lt;RE&gt;(re)) &gt; { return math_vector_expr&lt; math_vector_expr&lt;LeftExpr,BinaryOp,RightExpr&gt; const&amp;, plus_op&lt;value_type&gt;, decltype(std::forward&lt;RE&gt;(re)) &gt;(*this, std::forward&lt;RE&gt;(re)) ; } auto le() -&gt; typename std::add_lvalue_reference&lt;LeftExpr&gt;::type { return l_; } auto le() const -&gt; typename std::add_lvalue_reference&lt; typename std::add_const&lt;LeftExpr&gt;::type &gt;::type { return l_; } auto re() -&gt; typename std::add_lvalue_reference&lt;RightExpr&gt;::type { return r_; } auto re() const -&gt; typename std::add_lvalue_reference&lt; typename std::add_const&lt;RightExpr&gt;::type &gt;::type { return r_; } auto operator [](std::size_t index) const -&gt; value_type { return BinaryOp::apply(le()[index], re()[index]); } private: LeftExpr l_; RightExpr r_; }; //=========================================================================== template &lt;typename T&gt; struct plus_op { static T apply(T const&amp; a, T const&amp; b) { return a + b; } static T apply(T&amp;&amp; a, T const&amp; b) { a += b; return std::move(a); } static T apply(T const&amp; a, T&amp;&amp; b) { b += a; return std::move(b); } static T apply(T&amp;&amp; a, T&amp;&amp; b) { a += b; return std::move(a); } }; //=========================================================================== template &lt;std::size_t N&gt; class math_vector { using impl_type = std::array&lt;long double, N&gt;; public: typedef typename impl_type::value_type value_type; math_vector() { using namespace std; fill(begin(v_), end(v_), impl_type{}); std::cout &lt;&lt; this &lt;&lt; ": math_vector()" &lt;&lt; endl; } math_vector(math_vector const&amp; mv) noexcept { using namespace std; copy(begin(mv.v_), end(mv.v_), begin(v_)); std::cout &lt;&lt; this &lt;&lt; ": math_vector(copy: " &lt;&lt; &amp;mv &lt;&lt; ")" &lt;&lt; endl; } math_vector(math_vector&amp;&amp; mv) noexcept { using namespace std; move(begin(mv.v_), end(mv.v_), begin(v_)); std::cout &lt;&lt; this &lt;&lt; ": math_vector(move: " &lt;&lt; &amp;mv &lt;&lt; ")" &lt;&lt; endl; } math_vector(std::initializer_list&lt;value_type&gt; l) { using namespace std; copy(begin(l), end(l), begin(v_)); std::cout &lt;&lt; this &lt;&lt; ": math_vector(initlist)" &lt;&lt; endl; } math_vector&amp; operator =(math_vector const&amp; mv) noexcept { using namespace std; copy(begin(mv.v_), end(mv.v_), begin(v_)); std::cout &lt;&lt; this &lt;&lt; ": math_vector op =(copy: " &lt;&lt; &amp;mv &lt;&lt; ")" &lt;&lt; endl; return *this; } math_vector&amp; operator =(math_vector&amp;&amp; mv) noexcept { using namespace std; move(begin(mv.v_), end(mv.v_), begin(v_)); std::cout &lt;&lt; this &lt;&lt; ": math_vector op =(move: " &lt;&lt; &amp;mv &lt;&lt; ")" &lt;&lt; endl; return *this; } ~math_vector() { using namespace std; std::cout &lt;&lt; this &lt;&lt; ": ~math_vector()" &lt;&lt; endl; } void swap(math_vector&amp; mv) { using namespace std; for (std::size_t i = 0; i&lt;N; ++i) swap(v_[i], mv[i]); } auto operator [](std::size_t index) const -&gt; value_type const&amp; { return v_[index]; } auto operator [](std::size_t index) -&gt; value_type&amp; { return v_[index]; } math_vector&amp; operator +=(math_vector const&amp; b) { for (std::size_t i = 0; i&lt;N; ++i) v_[i] += b[i]; return *this; } #ifndef DONT_USE_EXPR_TEMPL template &lt;typename LE, typename Op, typename RE&gt; math_vector(math_vector_expr&lt;LE,Op,RE&gt;&amp;&amp; mve) { for (std::size_t i = 0; i &lt; N; ++i) v_[i] = mve[i]; std::cout &lt;&lt; this &lt;&lt; ": math_vector(expr: " &lt;&lt; &amp;mve &lt;&lt; ")" &lt;&lt; std::endl; } template &lt;typename RightExpr&gt; math_vector&amp; operator =(RightExpr&amp;&amp; re) { for (std::size_t i = 0; i&lt;N; ++i) v_[i] = re[i]; return *this; } template &lt;typename RightExpr&gt; math_vector&amp; operator +=(RightExpr&amp;&amp; re) { for (std::size_t i = 0; i&lt;N; ++i) v_[i] += re[i]; return *this; } template &lt;typename RightExpr&gt; auto operator +(RightExpr&amp;&amp; re) const -&gt; math_vector_expr&lt; math_vector const&amp;, plus_op&lt;value_type&gt;, decltype(std::forward&lt;RightExpr&gt;(re)) &gt; { return math_vector_expr&lt; math_vector const&amp;, plus_op&lt;value_type&gt;, decltype(std::forward&lt;RightExpr&gt;(re)) &gt;( *this, std::forward&lt;RightExpr&gt;(re) ) ; } #endif // #ifndef DONT_USE_EXPR_TEMPL private: impl_type v_; }; //=========================================================================== template &lt;std::size_t N&gt; inline void swap(math_vector&lt;N&gt;&amp; a, math_vector&lt;N&gt;&amp; b) { a.swap(b); } //=========================================================================== #ifdef DONT_USE_EXPR_TEMPL template &lt;std::size_t N&gt; inline math_vector&lt;N&gt; operator +( math_vector&lt;N&gt; const&amp; a, math_vector&lt;N&gt; const&amp; b ) { math_vector&lt;N&gt; retval(a); retval += b; return retval; } template &lt;std::size_t N&gt; inline math_vector&lt;N&gt; operator +( math_vector&lt;N&gt;&amp;&amp; a, math_vector&lt;N&gt; const&amp; b ) { a += b; return std::move(a); } template &lt;std::size_t N&gt; inline math_vector&lt;N&gt; operator +( math_vector&lt;N&gt; const&amp; a, math_vector&lt;N&gt;&amp;&amp; b ) { b += a; return std::move(b); } template &lt;std::size_t N&gt; inline math_vector&lt;N&gt; operator +( math_vector&lt;N&gt;&amp;&amp; a, math_vector&lt;N&gt;&amp;&amp; b ) { a += std::move(b); return std::move(a); } #endif // #ifdef DONT_USE_EXPR_TEMPL //=========================================================================== template &lt;std::size_t N&gt; std::ostream&amp; operator &lt;&lt;(std::ostream&amp; os, math_vector&lt;N&gt; const&amp; mv) { os &lt;&lt; '('; for (std::size_t i = 0; i &lt; N; ++i) os &lt;&lt; mv[i] &lt;&lt; ((i+1 != N) ? ',' : ')'); return os; } //=========================================================================== int main() { using namespace std; try { { cout &lt;&lt; "CASE 1:\n"; math_vector&lt;3&gt; a{1.0, 1.1, 1.2}; math_vector&lt;3&gt; b{2.0, 2.1, 2.2}; math_vector&lt;3&gt; c{3.0, 3.1, 3.2}; math_vector&lt;3&gt; d{4.0, 4.1, 4.2}; math_vector&lt;3&gt; result = a + b + c + d; cout &lt;&lt; '[' &lt;&lt; &amp;result &lt;&lt; "]: " &lt;&lt; result &lt;&lt; "\n"; } cout &lt;&lt; endl; { cout &lt;&lt; "CASE 2:\n"; math_vector&lt;3&gt; result = math_vector&lt;3&gt;{1.0, 1.1, 1.2} + math_vector&lt;3&gt;{2.0, 2.1, 2.2} + math_vector&lt;3&gt;{3.0, 3.1, 3.2} + math_vector&lt;3&gt;{4.0, 4.1, 4.2} ; cout &lt;&lt; '[' &lt;&lt; &amp;result &lt;&lt; "]: " &lt;&lt; result &lt;&lt; "\n"; } } catch (...) { return 1; } } //=========================================================================== </code></pre>
    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.
    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.
 

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