Search code examples
c++arraysintvariadic-templatesnon-type

Convert int array to variadic template


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>


Solution

  • 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);
    }