I'm really happy with the perfect forwarding in C++11 and want to do something more complicated. It's somewhat a classic case. I have a template axis-aligned box class. The template argument is a vector class. So I have a classic constructor, that takes 2 vectors:
template <class T> struct base_vec2 {
typedef T scalar_type;
base_vec2 (T a, T b); // counsruct for two scalar calues
};
template <class T> struct base_vec3 {
typedef T scalar_type;
base_vec2 (T a, T b, T c); // counsruct for three scalar calues
};
template <class T> struct base_box {
typedef typename T::scalar_type scalar_type;
T lower, upper; //<! upper and lower point
base_box<T> (const T& min, const T& max);
};
base_box<base_vec3<float>> box;
Naturally, one may want to implement a constructor which takes n scalar values and pass them to the lower and upper constructors. This is what I came up with:
template <class T> struct base_box {
.....
template <typename... Ts> base_box<T> (scalar_type s1, scalar_type s2, scalar_type s3, scalar_type s4, Ts&&... ts) {
base_box_construct<T, scalar_type, (4 + sizeof...(ts))/2> _(lower, upper, s1, s2, s3, s4, stl::forward<Ts>(ts)...);
}
};
base_box<base_vec2<float>> box(1, 2, 3, 4);
base_box<base_vec3<float>> box(1, 2, 3, 4, 5, 6);
base_box_construct do the actual magic:
template <class T, class A>
struct base_box_construct<T, A, 2> {
template <typename... Ts>
base_box_construct(T& lower, T& upper, A s1, A s2, A s3, A s4, Ts&&... ts)
{
lower = T(a1, a2);
upper = T(a3, a4);
}
};
template <class T, class A>
struct base_box_construct<T, A, 3> {
template <typename... Ts>
base_box_construct(T& lower, T& upper, A s1, A s2, A s3, A s4, Ts&&... ts)
{
lower = T(s1, s2, s3);
upper = T(s4, stl::forward<Ts>(ts)...);
}
};
template <class T, class A>
struct base_box_construct<T, A, 4> {
template <typename... Ts>
base_box_construct(T& lower, T& upper, A s1, A s2, A s3, A s4, Ts&&... ts)
{
lower = T(s1, s2, s3, s4);
upper = T(stl::forward<Ts>(ts)...);
}
};
It's a bit tricky, since it works only with 2, 3 and 4 arguments per vector which is just what I need. But I was wondering if there is better way to implement it.