Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>What Konrad already explained can be put further to support nested invocations of operators, all executed lazily. In Konrad's example, he has an expression object that can store exactly two arguments, for exactly two operands of one operation. The problem is that it will only execute <em>one</em> subexpression lazily, which nicely explains the concept in lazy evaluation put in simple terms, but doesn't improve performance substantially. The other example shows also well how one can apply <code>operator()</code> to add only some elements using that expression object. But to evaluate arbitrary complex expressions, we need some mechanism that can <em>store</em> the structure of that too. We can't get around templates to do that. And the name for that is <code>expression templates</code>. The idea is that one templated expression object can store the structure of some arbitrary sub-expression recursively, like a tree, where the operations are the nodes, and the operands are the child-nodes. For a <em>very</em> good explanation i just found today (some days after i wrote the below code) see <a href="https://web.archive.org/web/20090421155750/http://ubiety.uwaterloo.ca/~tveldhui/papers/Expression-Templates/exprtmpl.html" rel="noreferrer">here</a>.</p> <pre><code>template&lt;typename Lhs, typename Rhs&gt; struct AddOp { Lhs const&amp; lhs; Rhs const&amp; rhs; AddOp(Lhs const&amp; lhs, Rhs const&amp; rhs):lhs(lhs), rhs(rhs) { // empty body } Lhs const&amp; get_lhs() const { return lhs; } Rhs const&amp; get_rhs() const { return rhs; } }; </code></pre> <p>That will store any addition operation, even nested one, as can be seen by the following definition of an operator+ for a simple point type:</p> <pre><code>struct Point { int x, y; }; // add expression template with point at the right template&lt;typename Lhs, typename Rhs&gt; AddOp&lt;AddOp&lt;Lhs, Rhs&gt;, Point&gt; operator+(AddOp&lt;Lhs, Rhs&gt; const&amp; lhs, Point const&amp; p) { return AddOp&lt;AddOp&lt;Lhs, Rhs&gt;, Point&gt;(lhs, p); } // add expression template with point at the left template&lt;typename Lhs, typename Rhs&gt; AddOp&lt; Point, AddOp&lt;Lhs, Rhs&gt; &gt; operator+(Point const&amp; p, AddOp&lt;Lhs, Rhs&gt; const&amp; rhs) { return AddOp&lt; Point, AddOp&lt;Lhs, Rhs&gt; &gt;(p, rhs); } // add two points, yield a expression template AddOp&lt; Point, Point &gt; operator+(Point const&amp; lhs, Point const&amp; rhs) { return AddOp&lt;Point, Point&gt;(lhs, rhs); } </code></pre> <p>Now, if you have</p> <pre><code>Point p1 = { 1, 2 }, p2 = { 3, 4 }, p3 = { 5, 6 }; p1 + (p2 + p3); // returns AddOp&lt; Point, AddOp&lt;Point, Point&gt; &gt; </code></pre> <p>You now just need to overload operator= and add a suitable constructor for the Point type and accept AddOp. Change its definition to:</p> <pre><code>struct Point { int x, y; Point(int x = 0, int y = 0):x(x), y(y) { } template&lt;typename Lhs, typename Rhs&gt; Point(AddOp&lt;Lhs, Rhs&gt; const&amp; op) { x = op.get_x(); y = op.get_y(); } template&lt;typename Lhs, typename Rhs&gt; Point&amp; operator=(AddOp&lt;Lhs, Rhs&gt; const&amp; op) { x = op.get_x(); y = op.get_y(); return *this; } int get_x() const { return x; } int get_y() const { return y; } }; </code></pre> <p>And add the appropriate get_x and get_y into AddOp as member functions:</p> <pre><code>int get_x() const { return lhs.get_x() + rhs.get_x(); } int get_y() const { return lhs.get_y() + rhs.get_y(); } </code></pre> <p>Note how we haven't created any temporaries of type Point. It could have been a big matrix with many fields. But at the time the result is needed, we calculate it <em>lazily</em>. </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