Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create std::array with initialization list without providing size directly [duplicate]

How can I make a3 compile?

int main() {     int a1[] = { 1, 2, 3 };     std::array<int, 3> a2 = { 1, 2, 3 };     std::array<int> a3 = { 1, 2, 3 }; } 

It's very inconvenient, and brittle, to hard-code the size of the array when using an initialization list, especially long ones. Is there any work around? I hope so otherwise I'm disappointed because I hate C arrays and std::array is supposed to be their replacement.

like image 840
Neil Kirk Avatar asked Oct 14 '14 02:10

Neil Kirk


People also ask

How do you initialize an entire array with the same value?

Initializer List: To initialize an array in C with the same value, the naive way is to provide an initializer list. We use this with small arrays. int num[5] = {1, 1, 1, 1, 1}; This will initialize the num array with value 1 at all index.

How do you initialize an entire array in C++?

1. Using Initializer List. int arr[] = { 1, 1, 1, 1, 1 }; The array will be initialized to 0 if we provide the empty initializer list or just specify 0 in the initializer list.

Does std :: array initialize?

std::array contains a built-in array, which can be initialized via an initializer list, which is what the inner set is. The outer set is for aggregate initialization.

What happens when an array is initialized with more Initializers as compared to its size?

An initializer-list is ill-formed if the number of initializer-clauses exceeds the number of members or elements to initialize.


2 Answers

There is currently no way to do this without rolling your own make_array, there is a proposal for this N3824: make_array which has the following scope:

LWG 851 intended to provide a replacement syntax to

array<T, N> a = { E1, E2, ... }; 

, so the following

auto a = make_array(42u, 3.14); 

is well-formed (with additional static_casts applied inside) because

array<double, 2> = { 42u, 3.14 }; 

is well-formed.

This paper intends to provide a set of std::array creation interfaces which are comprehensive from both tuple’s point of view and array’s point of view, so narrowing is just naturally banned. See more details driven by this direction in Design Decisions.

It also includes a sample implementation, which is rather long so copying here is impractical but Konrad Rudolph has a simplified version here which is consistent with the sample implementation above:

template <typename... T> constexpr auto make_array(T&&... values) ->     std::array<        typename std::decay<            typename std::common_type<T...>::type>::type,        sizeof...(T)> {     return std::array<         typename std::decay<             typename std::common_type<T...>::type>::type,         sizeof...(T)>{std::forward<T>(values)...}; } 
like image 186
Shafik Yaghmour Avatar answered Oct 17 '22 08:10

Shafik Yaghmour


You're being a little overdramatic when you say "such a horribly complex (to me) function is required". You can make a simplified version yourself, the proposal also includes a "to_array" function to convert C-arrays and deducing the type from the first parameter. If you leave that out it gets quite manageable.

template<typename T, typename... N> auto my_make_array(N&&... args) -> std::array<T,sizeof...(args)> {     return {std::forward<N>(args)...}; } 

which you can then call like

auto arr = my_make_array<int>(1,2,3,4,5); 

edit: I should mention that there actually is a version of that in the proposal that I overlooked, so this should be more correct than my version:

template <typename V, typename... T> constexpr auto array_of(T&&... t)     -> std::array < V, sizeof...(T) > {     return {{ std::forward<T>(t)... }}; } 
like image 20
PeterT Avatar answered Oct 17 '22 08:10

PeterT