Search code examples
c++c++17variadic-templatestemplate-meta-programming

How can you perform arithmetic on an element of a non-type parameter pack?


I want a method that returns an object with a modified parameter pack. For example, the Nth template parameter is increased by 1.

template<size_t... Ni>
struct Test
{
    template<size_t Nth>
    constexpr auto RunTest()
    {
        // What should be written here?
    }
};

int main()
{
    Test<2, 2, 2> t1;
    Test<2, 3, 2> t2 = t1.RunTest<1>(); // How to make this work?
}

Solution

  • If you can afford a helper method, the following way should work starting from C++14:

    #include <utility>
    #include <type_traits>
    
    template <std::size_t... Ni>
    struct PackHolder
     {
       template <std::size_t Nth, std::size_t ... Is>
       constexpr auto IncrementHelper (std::index_sequence<Is...>)
          -> PackHolder<(Ni + (Nth == Is))...>
        { return {}; }
    
       template <std::size_t Nth>
       constexpr auto IncrementPackElement()
        { return IncrementHelper<Nth>(std::make_index_sequence<sizeof...(Ni)>{}); }
     };
    
    int main()
     {
       PackHolder<2, 2, 2> t1;
    
       auto t2 = t1.IncrementPackElement<1>();
    
       static_assert( std::is_same<decltype(t2), PackHolder<2, 3, 2>>::value, "!" );
     }