C++17 allows us to have std::array
‘s template arguments deduced.
(please enter here with a clear understanding of what we mean when we say “array type” in the realm of std::array
)
E.g., I can write
1 |
std::array ints = { 1, 2, 3 }; |
and ints
will yield the std array of type std::array<int, 3>
.
My question is: what if I wanted to specify only the type argument of the array but have the size of the array automatically determined? The following does not work since it seems like all template arguments have to be specified:
1 |
std::array<size_t> sizes = { 1, 2, 3 }; |
Above your compiler might say: ‘std::array’: too few template arguments.
Is it possible to have the size of the array determined automatically by template argument deduction? If not, is it possible to create an array by only specifying its type but not its size?
Homemade solution without C++20
Conceptually one does not need always to be explicit about the result type. Let me use my own make_array
:
1 2 3 4 5 6 7 8 |
template< typename ... T, typename CT = std::common_type_t< T... > > constexpr auto make_array(T&& ... t) -> std::array< CT , sizeof...(T)> { return { { static_cast<CT>( std::forward<T>(t) ) ...} }; } |
Slightly simpler usage is allowed:
1 |
constexpr auto std_arr = make_array(-5.0, 0.0, 5.0, 10.0); |
The issue here might be, we are not exactly certain, what type of std::array
(element) we will get. Provided we do care about it.
1 |
const auto std_arr = make_array(-5.0, 0, 5.0, 10.0, 42.13f ); |
If one’s bedtime reading is ISO C++ standard doc, one might be sure what type will come out of std::common_type
the tool chain in use. For the rest of us, literal suffixes will help
1 |
constexpr auto sizes = make_array( 1UL, 2UL, 3UL ); |
But why stop with numbers?
One can collect quickly, into an array, instances from the same hierarchy. Not caring about the result type.
1 2 3 4 5 6 |
{ const auto exceptions = make_array( std::exception{"SE"}, std::runtime_error{"RE"}, std::logic_error{"LE"} ); } |
A bit useless but somewhat weird and wonderful snippet that is. But, one thing do remember: this is a compile-time situation. Thus, I might prefer:
1 |
constexpr auto sizes = std::array{ 1UL, 2UL, 3UL } ; |
Use C++20, if you prefer std::
There is also C++20 std::to_array
. For the exact result type:
1 |
constexpr auto sizes = std::to_array<size_t>({ 0, 1, 3 }); |
Alas, I do prefer not to use std::
lib.