I am relatively new to c++ templates, and am implementing some numerical routines. In particular, I have been looking through some code whose style is such that if it were to define a vector, it would be as
template <class Field>
class Vector2
{
private:
std::vector<Field> container;
public:
Vector2(size_t size) : container(std::vector<Field>(size, Field(0))) {}
Vector2(const Vector2<Field> &source) : container(source.container) {}
Field & operator[](size_t index) { return container.at(index); }
const Field & operator[](size_t index) const { return container.at(index); }
Vector2<Field> operator+( const Vector2<Field> & rhs) const {
if (rhs.container.size() != container.size())
throw new std::invalid_argument("wrong size");
Vector2<Field> sum(*this);
for (int i = 0; i < container.size(); i++)
sum[i] += rhs[i];
return sum;
}
};
However, if I were designing the class template, I would have chosen to specify the size in the template parameter:
template <int size, class Field>
class Vector1
{
private:
std::vector<Field> container;
public:
Vector1() : container(std::vector<Field>(size, Field(0))) {}
Vector1(const Vector1<size, Field> &source) : container(source.container) {}
Field & operator[](size_t index) { return container.at(index); }
const Field & operator[](size_t index) const { return container.at(index); }
Vector1<size, Field> operator+( const Vector1<size, Field> & rhs) const {
Vector1<size, Field> sum;
for (int i = 0; i < size; i++)
sum[i] += rhs[i];
return sum;
}
};
My thinking is that this would prevent things like adding two vectors of different dimensions, since they would be different classes. In particular, something like
Vector1<double> a (3);
Vector1<double> b (4);
Vector1<double> c = a + b;
would need run-time checking of the sizes, yet
Vector2<3,double> a;
Vector2<4,double> b;
Vector2<5,double> c = a + b;
won’t even compile. Since this code is part of a numerical analysis package, execution speed is of the essence, and I have to assume that the authors would have considered such things. This style is used throughout the code for vectors, matrices, and other objects that are to be interpreted as elements of numerically-parametrized sets (i.e. vector spaces of varying dimension).
So, my question is,
Are there any execution-speed considerations that would imply a preference for the constructor-parameter method vs. the template-parameter method?
Of course. If the vector size is a runtime parameter, then binary operations must check at runtime that operand sizes agree.
Ideally, a C++ numerical package should provide templates with runtime-specified sizes and compile-time-specified sizes, and they should be interchangeable. Specifying size at compile time can only improve performance.
You could implement your suggestion by replacing
std::vectorin the given implementation withstd::array/boost::array. If the template parameter is only used to define a runtime parameter, nothing is gained.