3

I have the following method

template <std::size_t N, std::size_t... Indices>
void doSomething()
{
    ...
};

It seems not possible to supply default values for Indices, e.g.

template <std::size_t N, std::size_t... Indices = std::make_index_sequence<N>>
void doSomething()
{
    ...
};

Compiler complains that

error: expected primary-expression before '>' token
template <std::size_t N, std::size_t... Indices = std::make_index_sequence<N>>
                                                                             ^~
error: template parameter pack 'Indices' cannot have a default argument
template <std::size_t N, std::size_t... Indices = std::make_index_sequence<N>>
                                    ^~~

Is there any way around this?

zhanginou
  • 177
  • 6
  • 2
    packs are not allowed to have default arguments. Generally they way to do this is to make a `template void doSomething()` version of `doSomething` and have that call the one with a pack with the desired pack that you want. – NathanOliver May 27 '22 at 01:18
  • BTW `std::make_index_sequence` is not `std::size_t...`. If legal, you would need something like `std::size_t... Indices = [0, 1, 42]`. – Jarod42 May 27 '22 at 09:44

2 Answers2

2

This is impossible. However, you can wrap parameter pack with index_sequence and expand them in the function body

#include <cstddef>
#include <utility>

template <std::size_t N, class Indices = std::make_index_sequence<N>>
void doSomething() {
  []<std::size_t... Is>(std::index_sequence<Is...>) {
    // expand parameter pack
  }(Indices{});
};

Demo

康桓瑋
  • 33,481
  • 5
  • 40
  • 90
2

There's already two excellent answers so far (including NathanOliver's comment). I think that having a couple of overloads that act as wrappers is really the simplest solution here, but just for completeness, let's provide your desired functionality in one function:

Often it's best to take as much of the template logic out of the parameter list as possible (separating inputs from logic):

template <std::size_t N, std::size_t... Indices>
void doSomething()
{
    using Ints
        = std::conditional_t<
            /* if */ (sizeof...(Indices) > 0),
                std::index_sequence<Indices...>,
            /* else */
                std::make_index_sequence<N>>;

    // ...
};

demo

Elliott
  • 2,603
  • 2
  • 18
  • 35