0

Consider the following piece of code:

struct foo {
  std::vector<int> v;
  foo(std::initializer_list<int> L) : v{L} {}
};

The code above compiles fine and initializes v as expected. Now consider the following piece of code:

struct bar {
  std::array<int, 3> a;
  bar(std::initializer_list<int> L) : a{L} {}
};

The above piece of code gives a compile error.

error: no viable conversion from 'std::initializer_list' to 'int'

Searching the web I found that the "proper" way to initialize a member std::array with a std::list_initializer is to use reinterpret_cast in the following manner:

bar(std::initializer_list<int> L) : a(reinterpret_cast<std::array<int, 3> const&>(*(L.begin()))) {}

Q:

Why I can initialize a member std::vector with an std::initializer_list in the initialization list of a constructor but I can't a member std::array?

Is the work-around showed above with reinterpret_cast the proper way to initialize a member std::array with a std::initializer_list?

101010
  • 41,839
  • 11
  • 94
  • 168

3 Answers3

6

std::array was designed (in the Boost library) to support the braces initialization syntax with C++03. The only way to do that in C++03 was as a POD (plain old data) type, one with no constructors. Initializer lists were introduced in C++11, along with std::array, but std::array was not changed from its Boost version to use initializer lists. So, it's historical.

By the way, note that the reinterpret_cast is dangerous here because the initializer list may contain fewer items than the array.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
1

a std::array is a thin wrapper around a C++ array, see it like

template<typename T, size_t N>
struct {
  T data[N];
}

So it doesn't have any constructor able to cope with a std::initializer_list, you must stick with a vector or copy the elements with something else (like std::copy) in the constructor.

Jack
  • 131,802
  • 30
  • 241
  • 343
1
foo(std::initializer_list<int> L) : v{L} {}

std::vector has a constructor that accepts a std::initializer_list as input. You are thus initializing the vector itself, not any particular element of the std::vector.

bar(std::initializer_list<int> L) : a{L} {}

std::array does not have a constructor that accepts a std::initializer_list as input (in fact, it does not have any constructors at all, it can only be initialized through aggregate initialization). You are thus trying to initialize a specific element of the array, which is why the compiler complains that it cannot convert a std::initializer_list to an int.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770