Consider the standard use of CRTP for some expression template engine that saves its children by value:
template <typename T, typename> struct Expr {}; template <typename T> struct Cst : Expr<T, Cst<T>> { Cst(T value) : value(std::move(value)) {} private: T value; }; template <typename T, typename L, typename R> struct Add : Expr<T, Add<T, L, R>> { Add(L l, R r) : l(std::move(l)), r(std::move(r)) private: L l; R r; };
and etc.
Now, when implementing the operator, we must follow the link, since the argument must be disabled to the desired type. The problem is that I found that I am implementing four (!) Versions of operator+ :
template <typename T, typename L, typename R> Add<T, L, R> operator+(Expr<T, L>&& l, Expr<T, R>&& r) { return Add<T, L, R>( std::move(static_cast<L&>(l)), std::move(static_cast<R&>(r))); } template <typename T, typename L, typename R> Add<T, L, R> operator+(const Expr<T, L>& l, Expr<T, R>&& r) { return Add<T, L, R>( static_cast<const L&>(l), std::move(static_cast<R&>(r))); } template <typename T, typename L, typename R> Add<T, L, R> operator+(Expr<T, L>&& l, const Expr<T, R>& r) { return Add<T, L, R>( std::move(static_cast<L&>(l)), static_cast<const R&>(r)); } template <typename T, typename L, typename R> Add<T, L, R> operator+(const Expr<T, L>& l, const Expr<T, R>& r) { return Add<T, L, R>( static_cast<const L&>(l), static_cast<const R&>(r)); }
In fact, if the goal is to minimize unnecessary copying, you need to distinguish between temporary (which can be moved) and lvalues ββ(which should be copied), therefore, four overloads.
In C ++ 03, βno problemβ: we use const references and copy all the time, period. In C ++ 11, we can do better, and that is the goal here.
Is there any trick that would allow me to write add logic once, or write a macro my best option is here (since the logic will be repeated for other operators)?
I am also open to other suggestions on how to write expression patterns with C ++ 11. Just think that the goal is to minimize copying, since the values ββstored in terminal nodes can be huge numbers or matrices (in my exact In this case, the terminal nodes may contain several megabytes of interpolated data, and copying is disabled for these objects - for other objects, copying is possible).