I am trying to write a C++ vector class that stores an array of data and allows performing mathematical operations on an element-by-element basis. I want to implement this in such a way that an expression a = b + c + d
should loop over all elements only once and directly write the sum b[i] + c[i] + d[i]
to a[i]
without creating intermediate vectors.
I was writing something like this:
template<class T, int N>
class VectorExpression {
public:
virtual T operator[] (int i) const = 0;
virtual ~VectorExpression() {}
}
template<class T, int N>
class MyVector : public VectorExpression<T, N> {
T data[N];
public:
T& operator[] (int i) { return data[i]; }
T& const operator[] (int i) const { return data[i]; }
MyVector<T,N>& operator=(const VectorExpression<T,N> &rhs) {
for (int i = 0; i < N; ++i)
data[i] = rhs[i];
return *this;
}
}
template<class T, int N>
class VectorSum : public VectorExpression<T, N> {
VectorExpression<T,N> &a, &b;
public:
VectorSum(VectorExpression<T,N> &aa, VectorExpression<T,N> &bb)
: a(aa), b(bb) {}
T operator[] (int i) const { return a[i] + b[i]; }
}
template<class T, int N>
VectorSum<T,N> operator+(const VectorExpression<T,N> &a,
const VectorExpression<T,N> &b)
{
return VectorSum<T,N>(a, b);
}
int main() {
MyVector<double,10> a, b, c, d;
// Initialize b, c, d here
a = b + c + d;
return 0;
}
Probably this functionality is provided by the valarray class but that's because I tried to strip it down to a minimal example.
I made operator[]
virtual because this allows nesting all kinds of expressions (e.g. a = !(-b*c + d)
) provided I would define all the operators and the corresponding classes similar to VectorSum
.
I use references because ordinary variables aren't polymorphic and pointers don't work with operator overloading.
Now my questions about this are:
In the statement
a = b + c + d;
, two temporaryVectorSum<double,10>
objects will be created to storeb + c
and(b+c) + d
respectively. Will they live long enough to make the polymorphic behavior work? More specifically,(b+c) + d
will store a reference tob + c
, but will that object still exist whenoperator=
is called? According to this post all temporaries should exist untiloperator=
returns, but does this also hold for older versions of C++?If not, then how is this done? The only alternative I see would be to allocate the
VectorSum
objects usingnew
, return them by reference and then delete them in theoperator=
functions, but that seems a little cumbersome, and probably a lot less efficient. I'm also not sure if it is always safe.(Minor question) Is it okay to override the return type
T
ofVectorExpression::operator[]
byT& const
inMyVector
?
EDIT
I had wrong argument types in operator+: changed them from VectorSum
to VectorExpression
.