I'm trying to implement a constructor for a C++ vector class template that is both efficient and convenient to use. The latter is, of course, somewhat subjective — I'm aiming at something like Vec2D myVec = Vec2D({1.0, 2.0})
.
To start with, I'm thinking about a class template for fixed-length vectors, so no immediate use for std::vector
I'd say. With template <typename T, unsigned short n>
, two options to store the elements of the vector would be T mElements[n]
or std::array<T, n> mElements
. I would go with the latter (same storage and some added benefits compared to the former).
Now, on to the constructor (and the question) — what should be its parameter? The following options come to mind:
- Using
std::array<T, n> initElements
would require the use of double curved brackets for initialisation as it is an aggregate, i.e.Vec2D myVec = Vec2D({{1.0, 2.0}})
. Omitting the outer curly brackets might still compile, though results in a warning. Additionally, if we were to generalise this to a 2D array, e.g. for a matrix class template, it would require quadruple curved brackets (or triple when omitting the outer pair again, taking a warning for granted). Not so convenient. - Using
T initElems[]
would require e.g.double dElems[2] = {1.0, 2.0}
followed byVec2D myVec = Vec2D(dElems)
, it is not possible to directly pass{1.0, 2.0}
as argument. Not so convenient. - Using
std::initializer_list<T>
, which would allowVec2D myVec{1.0, 2.0}
. This also nicely generalises to a 2D array. However, I don't see how one would use this as a constructor when overloading operators, sayoperator +
. - Using
std::vector<T>
. This allows the use ofVec2D myVec = Vec2D({1.0, 2.0})
, nicely generalises to 2D arrays, and is easy to use in overloaded operators. However, it does not seem very efficient.
The (intentionally basic) code below reflects the last option. Are there alternatives which are more efficient, without losing convenience?
template <typename T, unsigned short n>
class Vector {
public:
std::array<T, n> mElements;
// Constructor
Vector(std::vector<T> initElements) {
for (unsigned short k = 0; k < n; k++) {
mElements[k] = initElements[k];
}
}
// Overloaded operator +
Vector operator + (const Vector& rightVector) const {
std::vector<T> sumVec(n);
for (unsigned short k = 0; k < n; k++) {
sumVec[k] = mElements[k] + rightVector.mElements[k];
}
return Vector(sumVec);
}
};
With the usage
using Vec2D = Vector<double, 2>;
Vec2D myVec = Vec2D({1.0, 2.0});