Say I have an int array like int arr[N]
and say arr[i]
are from a tiny domain (e.g. 1-10). Say I also have a variadic templated class with a common interface (abstract class)
template <int... A>
class FooImpl : public Foo
{
}
The question is how do I implement a function:
Foo* getFoo(int arr[N]);
or maybe better:
Foo* getFoo(int* pint, int size);
which would return FooImpl
with template arguments corresponding my array? For example for arr = {4,2,6,1}
I would get FooImpl<4,2,6,1>
I found the answer to my question. The trick is in using struct variadic templates instead of function variadic templates which I initially tried with. I use _getFoo_impl struct with func function which builds up element by element.
Let's assume the elements are in range [1-5] and the size <= 4 and then the code looks as following:
class Foo
{
};
template <int...A>
class FooImpl : Foo {
};
template<int...As>
struct _getFoo_impl
{
static Foo* func(int *arr, int sz)
{
if (sz == 0)
return new FooImpl<As...>;
switch (*arr)
{
case 1: return _getFoo_impl<As..., 1>::func(arr + 1, sz - 1);
case 2: return _getFoo_impl<As..., 2>::func(arr + 1, sz - 1);
case 3: return _getFoo_impl<As..., 3>::func(arr + 1, sz - 1);
case 4: return _getFoo_impl<As..., 4>::func(arr + 1, sz - 1);
case 5: return _getFoo_impl<As..., 5>::func(arr + 1, sz - 1);
default: throw "element out of range";
}
}
};
template<int A1, int A2, int A3, int A4, int A5>
struct _getFoo_impl<A1, A2, A3, A4, A5>
{
static Foo* func(int*, int sz) {
std::terminate();
}
};
Foo* getFoo(int *arr, int size)
{
return _getFoo_impl<>::func(arr, size);
}