I\'m trying to implement a simple vector
class which uses expression templates in order to avoid that expressions such as vector w = x + y + z
are impl
I was facing a similar decision in my expression template code quite some time ago. The choice of how to store the wrapped arrays is thereby of central importance and should be made with care. But let's assume you already settled for references: that is, if you have code like
vector a;
vector b;
auto c = a + b;
a
and b
are stored by const-reference. This implies that as long as you use c
, the original vectors have to be kept alive. (Other choices would be store-by-value, which can be expensive, or store-by-(wrapped)-shared-pointer, which let's you use c
even if a
or b
left their scope but comes with a call overhead.)
Ok, but now as you settled for references, you obviously want to avoid references to a temporary. For that, C++ move semantics offers already anything you need:
template<typename E1, typename E2>
auto operator+(E1&& e1, E2&& e2)
{
using value_type = decltype(e1[0] + e2[0]);
return vector_binary_operation<E1, E2, std::plus<value_type> >
{std::forward<E1>(e1), std::forward<E2>(e2), std::plus<value_type>{}};
}
The difference to your code is in the type deduction of the used rvalue references E1&&
and E2&&
. Their purpose is to indicate whether the function got a valid and named object or a temporary. Based on this information, in this function you can make the choice how to store the passed references in the returned expression classes.
For example, if you now add two vectors
auto c = a + b;
E1
and E2
will be deduced both as vector&
. On the opposite, if you have
auto d = (a + b) + b;
E1
is vector_binary_operation<vector&, vector&, std::plus<> >
-- no reference here -- whereas E2 is still vector&
.