You can actually use the function as a template parameter, here called Gen
:
template <bool B, size_t Count, int Current, int Gen(size_t), int ... Nums>
struct generator;
template <size_t Count, int Current, int Gen(size_t), int ... Results>
struct generator<false,Count,Current, Gen, Results...>
{
constexpr static std::array<int,Count> array
generator<Current+1==Count,Count,Current+1,Gen,
Gen(Current), Results...>::array;
};
template <size_t Count, int Current, int Gen(size_t), int ... Results>
struct generator<true,Count,Current,Gen,Results...>
{
constexpr static std::array<int,Count> array{{Results...}};
};
With this it actually works to pass a constexpr function to the template (if the type matches exactly):
// helper to hide the "internal" template parameters
template <size_t Count, int Gen(size_t)>
struct gen {
constexpr static std::array<int, Count> array = generator<false, Count, 0, Gen>::array;
};
constexpr int f(size_t i) { return i * i * i; }
int main()
{
auto arr = gen<10,f>::array;
for (auto i : arr) {
std::cout << i << " ";
}
return 0;
}
You can also switch around the Gen(Current)
and Results...
parameters to get the values at the "correct" array indexes.