When deducing a parameter pack from a std::make_index_sequence, why can it not be used as default argument?

Viewed 39

To keep the template magic as deep in my code as possible I would like to use std::make_index_sequence as a default argument but this does not seem to compile and I don't quite understand why that is.

As an example take this case without default args, which compiles (Bare in mind this is a simplified example not my real use case):

#include <utility>

template <std::size_t... TIndicies>
std::size_t FunctNoDefaultArgs(std::index_sequence<TIndicies...>)
{
    return (TIndicies + ... + 0);
}

int main()
{
    return FunctNoDefaultArgs(std::make_index_sequence<5>{});
}

This works just fine.

So I wanted to move the std::make_index_sequence<5>{} to be a default argument and do the following:

#include <utility>

template <std::size_t... TIndicies>
std::size_t FunctDefaultArgs(std::index_sequence<TIndicies...> = std::make_index_sequence<5>{})
{
    return (TIndicies + ... + 0);
}

int main()
{
    return FunctDefaultArgs();
}

This does not compile in either MSVC, Clang or gcc. Could someone explain why?

CompilerExplorer

1 Answers

Template parameter deduction is the first order of business here. You have to figure out what exactly are you calling, before you start worrying about its parameters.

FunctDefaultArgs();

Ok, what are the template parameters here? You can't deduce them. There's nothing to deduce. It's entirely possible that, for example, some particular set of template parameters will wind up at a template specialization that has completely different parameters, default or non-default.

Template parameters have to be deduced first, before anything is done.

Fortunately, the solution -- that effects the same result -- is trivial. It should be just an additional declaration/definition:

inline auto FunctNoDefaultArgs()
{
    return FunctNoDefaultArgs(std::make_index_sequence<5>{});
}
Related