C++ limiting a method for an rvalue caller, an expression evaluator example There are many ways to implement a math expressions evaluator (I focus here just on the evaluator part, without any parsing).

I want to explore a certain implementation to support the following main:

int main() {
    Expression e = Sum( Sum(Number(2), Number(3)), Number(-1) );
    cout &lt;&lt; e &lt;&lt; "=" &lt;&lt; e.eval() &lt;&lt; endl;
}


The expected output is:

((2+3)+-1)=4




A basic notion: there are some temporary objects created there. We should better move them. 
So I came up with the following code I would like to consult about.



BaseExpression - an abstract base for all expressions

class BaseExpression {
public:
    virtual ~BaseExpression() {}
    // what do you think about the concept of the method 'get_unique_copy()' below?
    virtual std::unique_ptr&lt;BaseExpression&gt; get_unique_copy() &amp;&amp; = 0;
    virtual double eval()const = 0;
    virtual void print(ostream&amp; out)const = 0;
};




Expression - the actual non-abstract to hold an expression

class Expression {
    std::unique_ptr&lt;BaseExpression&gt; _e;
public:
    Expression(nullptr_t) {}
    Expression(BaseExpression&amp;&amp; e) 
    : _e(std::move(e).get_unique_copy()) {}
    ~Expression() {}
    Expression(Expression&amp;&amp; e) noexcept : _e(std::move(e._e)) {}
    Expression&amp; operator=(Expression&amp;&amp; e) noexcept { std::swap(_e, e._e); return *this; }
    double eval() const { return _e-&gt;eval(); }
    friend ostream&amp; operator&lt;&lt;(ostream&amp; out, const Expression&amp; e) {
        e._e-&gt;print(out);
        return out;
    }
};




Sum - an example of an actual expression

class Sum: public BaseExpression {
    Expression _e1{nullptr}, _e2{nullptr};
public:
    Sum(BaseExpression&amp;&amp; e1, BaseExpression&amp;&amp; e2) 
        : _e1(std::move(e1)), _e2(std::move(e2)) {}
    Sum(const Sum&amp; s) = delete;
    Sum&amp; operator=(const Sum&amp; s) = delete;
    Sum(Sum&amp;&amp; s) noexcept {
        std::swap(_e1, s._e1);
        std::swap(_e2, s._e2);
    }
    // what do you think about the implementation of 'get_unique_copy()' below? is it safe?
    virtual std::unique_ptr&lt;BaseExpression&gt; get_unique_copy() &amp;&amp; {
        return std::make_unique&lt;Sum&gt;(std::move(*this));
    }
    virtual double eval()const override {
        return _e1.eval() + _e2.eval();
    }
    virtual void print(ostream&amp; out)const override {
        out &lt;&lt; '(' &lt;&lt; _e1 &lt;&lt; '+' &lt;&lt; _e2 &lt;&lt; ')';
    }
};




Number - the simplest actual expression

class Number: public BaseExpression {
    double _d;
public:
    Number(double d) : _d(d) {}
    // what do you think about the duplication of 'get_unique_copy()' in each derived?
    // is there a way to avoid the duplication, apart from ugly Macros?
    virtual std::unique_ptr&lt;BaseExpression&gt; get_unique_copy() &amp;&amp; {
        return std::make_unique&lt;Number&gt;(std::move(*this));
    }
    virtual double eval()const override {
        return _d;
    }
    virtual void print(ostream&amp; out)const override {
        out &lt;&lt; _d;
    }
};




What do you think?

http://coliru.stacked-crooked.com/a/9843afbe4e9ed4d8
I had a bunch of sections detailing the various aspects of your design that could be improved, but I ended up scrapping most of it, because at the end of the day, it can be resumed in two specific things:

But first: The idea of forcing RValues here is severely misguided. Forcing RValue usage should be limited to cases where things would break otherwise, not to enforce coding practices. What if someone wants to create a complex sub-expression and reuse it a few times? Tough luck!

1. Expression as a wrapper is misguided.

I do not like wrappers that exist just for the sake of giving value semantics to something. Value vs reference semantics should be delegated to the user as much as humanly possible as long as type erasure is not invovled. Specifically, someone will inevitably write std::unique_ptr&lt;Expression&gt; at some point in the future.

2. This is unjustifiably complicated.

You can obtain the same functionallity with bog-standard code, no need to get fancy. The trick is to separate the Sum() function in the API from the Sum type in the implementation.

class Expression {
public:
  virtual ~Expression() {};
  virtual std::unique_ptr&lt;Expression&gt; clone() const = 0;
};

class SumExpr : public Expression {
  std::unique_ptr&lt;Expression&gt; e1_;
  std::unique_ptr&lt;Expression&gt; e2_;
public:
  SumExpr(std::unique_ptr&lt;Expression&gt; e1, 
          std::unique_ptr&lt;Expression&gt; e2)
    : e1_(std::move(e1))
    , e1_(std::move(e2)) {}

  std::unique_ptr&lt;Expression&gt; clone() override {
    return std::make_unique&lt;SumExpr&gt;(e1-&gt;clone(), e2-&gt;clone());
  }
};

std::unique_ptr&lt;Sum&gt; Sum(std::unique_ptr&lt;Expression&gt; e1,
                         std::unique_ptr&lt;Expression&gt; e2) {
  return std::make_unique&lt;SumExpr&gt;(std::move(e1), std::move(e2));
}


Note that is is not "quite" how I'd go about implementing this, but this way matches your current functionality.

Bonus: Implement printing to ostream as operator &lt;&lt;

It's a shame that operator&lt;&lt;(std::ostream&amp;, Sum const&amp;) is not implemented. print() should delegate to it ideally, so that stream &lt;&lt; Sum()...; can work

Now, at first glance, it would seem that this would require some really annoying boilerplate, but you can get around that using some crafty CRTP:

class Expression {
public:
  virtual std::ostream&amp; print(std::ostream&amp;) const = 0;
};

template&lt;typename CRTP_T&gt;
class ExpressionImpl : public Expression {
  std::ostream&amp; print(std::ostream&amp; stream) const override {
    return stream &lt;&lt; *static_cast&lt;CRTP_T const*&gt;(this);
  }
};

class Sum : public ExpressionImpl&lt;Sum&gt; {
  friend std::ostream&amp; operator&lt;&lt;(std::ostream&amp;, Sum const&amp;) {
    ...
  }
};


As an exercise to the reader, you can similarly create a BinaryExpression&lt;CRTP_T&gt; to avoid having to reimplement the clone() function in every single leaf class.