Search code examples
c++templatesnon-type

Calling Template Function with Multiple Parameter Values


I would like to call a template function foo with a sequence of different (non-type) parameters, taking consecutive integer values between a lower and upper bound. For instance:

template <int K> void foo(){ ... }

int const UPPER = 10, LOWER = 5;

for(int i = LOWER; i <= UPPER; i++)
    foo<i>();

This, of course, won't work since i is not known at compile time. I am looking for a way to achieve this sort of program without having to write something like:

foo<5>(); foo<6>(); foo<7>(); foo<8>(); foo<9>(); foo<10>();

This is in particular because I intend on changing UPPER and LOWER from one execution to the next.

My only idea was to create a constant array of the integers which will be sent to the template parameter:

int const arr[6] = {5, 6, 7, 8, 9, 10};

for(int i = LOWER; i <= UPPER; i++)
    foo<arr[i]>();

But, again, although the elements of the array are constant, i is not known at compile-time so neither is arr[i]. Any suggestions?

Thank you in advance.


Solution

  • You can use two templates and std::enable_if to select one of them, depending on whether Lower is equal to Upper. In case they are equal, we do nothing. Otherwise, we invoke foo<Lower>() and recurse with parameters Lower + 1 and Upper.

    template <int Lower, int Upper>
    typename std::enable_if<Lower == Upper, void>::type callFoo()
    {
    
    }
    
    template <int Lower, int Upper>
    typename std::enable_if<Lower != Upper, void>::type callFoo()
    {
        static_assert(Lower < Upper, "Lower must be less than or equal to Upper");
    
        foo<Lower>();
        callFoo<Lower + 1, Upper>();
    }
    

    Given this template, the following line will invoke foo<K>() for K values 5, 6, 7, 8, 9, 10.

    callFoo<5, 11>();