For ar
, here's an approach:
namespace detail {
template<typename T, T... Ns>
constexpr auto make_iota_array(T const offset, std::integer_sequence<T, Ns...>) noexcept
-> std::array<T, sizeof...(Ns)> {
return {{(Ns + offset)...}};
}
}
template<typename T, T N>
constexpr auto make_iota_array(T const offset = {}) noexcept {
static_assert(N >= T{}, "no negative sizes");
return detail::make_iota_array<T>(offset, std::make_integer_sequence<T, N>{});
}
// ...
auto ar = make_iota_array<int, 10>(99);
Online Demo
For ar2
, here's an approach:
namespace detail {
template<typename T, typename F, std::size_t... Is>
constexpr auto generate_array(F& f, std::index_sequence<Is...>)
-> std::array<T, sizeof...(Is)> {
return {{f(std::integral_constant<std::size_t, Is>{})...}};
}
}
template<typename T, std::size_t N, typename F>
constexpr auto generate_array(F f) {
return detail::generate_array<T>(f, std::make_index_sequence<N>{});
}
// ...
auto ar2 = generate_array<C, 3>([](auto i) -> C { return {i, i * 1.12f}; });
Online Demo
(noexcept
is more-or-less optional here IMO, and omitted here for brevity, but is present in the demos.)
N.b. both are fully constexpr
, but since generate_array
is likely to be used with lambdas it won't be constexpr
in practice until C++17 (demo). Also n.b. generate_array
will work with non-copyable/non-movable types in C++17 due to guaranteed copy elision (demo).