First of all, you may want to re-read the the preface post. I recently edited it, adding a specialisation for 1-element array, to contain just the elementfirst, and not the (empty) structurerest.

Why?

Because I spotted that without the specialisation, the size of the structure was off by some bytes (depending on the alignment). This is because even an empty struct can never be 0-sized. Avoiding the empty struct altogether was the only way to have the smallest value forsizeof(VecImpl<T, X>) to be reported.

Back toVecImpl, let’s see how we can assign values to the elements:

VecImpl<int, 5> q;
q.first = 0;
q.rest.first = 1;
q.rest.rest.first = 2;
q.rest.rest.rest.first = 3;
q.rest.rest.rest.rest.first = 4;

This is quite inconvenient.

We would like to have a nice initialization with, say, a constructor.

By exploiting recursive definition of our structure, we can provide a (recursive) constructor to it.

The easiest one is for the 1-element array:

template <typename T> struct VecImpl<T, 1> {
    T first;
    VecImpl(T f) : first(f) {} 
};

For the recursive structure, we can use a recursive variadic-templated constructor

template <typename T, int N> struct VecImpl {
// ...
    template <typename ...Ts> VecImpl(T f, Ts ...r) : first(f), rest(r...) {}
};

Easy, isn’t it?

And here’s the usage:

VecImpl<int, 5> q(0, 1, 2, 3, 4);

In the next post we’ll see how to access elements of the vector.

Leave a Reply