The size() member functions of std::initializer_list and std::array have identical signatures:
constexpr size_type size() const noexcept;
Both are constexpr. However, std::array::size() can be used in constexpr context, but std::initializer_list::size() can't:
std::initializer_list<int> il{1, 2, 3, 4};
constexpr std::size_t il_size = il.size(); // (1) - fails with GCC and Clang (*)
std::array<int, 4> arr{1, 2, 3, 4};
constexpr std::size_t arr_size = arr.size(); // (2) - OK
(*) The error is:
in 'constexpr' expansion of 'il.std::initializer_list<int>::size()' error: the value of 'il' is not usable in a constant expression
As far as I understand, the fact that (1) fails and (2) succeeds is perfectly reasonable because constexpr member function of a class template may fail to satisfy constexpr requirements.
I have two related questions:
- Why isn't
std::initializer_listimplemented in a way such that(1)compiles? Is there something in the standard that prevents such an implementation? Given that
(1)fails, what is the purpose of markingstd::initializer_list::size()asconstexpr? The only use case seems to be this one:constexpr std::initializer_list<int> il{1, 2, 3, 4}; // note constexpr constexpr std::size_t il_size = il.size();