c++templatesc++14variadic-templatesindex-sequence

Using default arguments for std::index_sequence


I have difficulties to understand the following. Why does this code compile

template <size_t N, size_t... N_i, size_t... M_i>
auto foo2(std::index_sequence<M_i...> = std::make_index_sequence<N>())
{

    constexpr size_t values[] = {N_i...};
    return A<values[M_i]...>();
}


template <size_t N,size_t... N_i>
auto foo()
{
    return foo2<N,N_i...>(std::make_index_sequence<N>());
}


int main()
{
 foo<2, 1,2,3>();
}

but this not (where I use the default argument of foo2):

template <size_t N, size_t... N_i, size_t... M_i>
auto foo2(std::index_sequence<M_i...> = std::make_index_sequence<N>())
{

    constexpr size_t values[] = {N_i...};
    return A<values[M_i]...>();
}


template <size_t N,size_t... N_i>
auto foo()
{
    return foo2<N,N_i...>();
}


int main()
{
 foo<2, 1,2,3>();
}

Many thanks in advance.


Solution

  • Given:

    template <size_t N, size_t... N_i, size_t... M_i>
    auto foo2(std::index_sequence<M_i...> = std::make_index_sequence<N>());
    

    You can't explicitly specify M_i (because the sequence would just get swallowed up as part of N_i). If you specify an argument, then the compiler can use template argument deduction to work out what M_i is. If you don't specify an argument, then the compiler has no way to deduce what M_i is (and it needs to know that before it can start deciding you need a default argument, and what that argument is).

    Assuming that this is a smaller part of a larger whole, then the fix is to write

    template <size_t N, size_t... N_i, size_t... M_i>
    auto foo2(std::index_sequence<M_i...>)
    {
    
        constexpr size_t values[] = {N_i...};
        return A<values[M_i]...>();
    }
    
    
    template <size_t N,size_t... N_i>
    auto foo2()
    {
        return foo2<N,N_i...>(std::make_index_sequence<N>());
    }
    

    Then you can indeed write:

    template <size_t N,size_t... N_i>
    auto foo()
    {
        return foo2<N,N_i...>();
    }