std::array
requires compile time constant, function arguments are not constexpr even in constant expression.
So not possible with exactly your interface.
If you agree with Range range_1(std::integral_constant<std::size_t, 10>{});
instead, you might do:
template <std::size_t N>
using IC = std::integral_constant<std::size_t, N>;
// Possibly create udl with operator ""_ic to have 42_ic syntax
constexpr std::size_t dynamic_extent = -1;
template <std::size_t N>
struct Range
{
Range(IC<N>) {}
std::array<int, N> data{};
};
template <>
struct Range<dynamic_extent>
{
Range(std::size_t N) : data(N) {}
std::vector<int> data;
};
// CTAD
template <std::size_t N> Range(IC<N>) -> Range<N>;
Range(std::size_t) -> Range<dynamic_extent>;
// Testing
Range r1(IC<10>{});
Range r2(10);
static_assert(std::is_same_v<decltype(r1.data), std::array<int, 10>>);
static_assert(std::is_same_v<decltype(r2.data), std::vector<int>>);
Demo
Notice than CTAD is a all or nothing, so if you attend to have Range<T, N>
, it would not be directly possible.