If elements in std::initializer_list are always const values, why we have template method like begin()/end() and not cbegin()/cend()? This names (by conventions, comparing to e.g. std::vector) could suggest that both std::initializer_list method could return iterator, when they always return const_iterator.

1 Answer
1

While I can't provide an insight on the reason why cbegin() and cend() are not part of std::initializer_list's interface in addition tobegin() and end(), there are certainly good reasons why the last two member functions ought to be there.

One reason is, for instance, that the range-based for loop is defined by the C++11 Standard precisely in terms of functions begin() and end() (Paragraph 6.5.4/1). Therefore, in order to make it possible to use it with initializer lists, std::initializer_list has to provide the begin() and end() member functions:

Moreover, it makes sense to consider that member functions cbegin() and cend() were not present before C++11: therefore, having begin() and end() on the interface of std::initializer_listallows making old generic algorithms written in terms of begin() and end() work with initializer lists as well, without requiring them to be rewritten.

You write:

These names (by conventions, comparing to e.g. std::vector) could suggest that both std::initializer_list method could return iterator, when they always return const_iterator.

Actually, this analogy is not very appropriate. std::vector's function begin(), for instance, returns an iterator when invoked on a non-const instance of std::vector (i.e. a mutable one, whose elements can be modified, added, and removed), and a const_iterator when invoked on a const instance (i.e. an immutable one, whose content cannot be altered):

Initializer lists are immutable collections by definition. Per Paragraph 18.9/2 of the C++11 Standard:

An object of type initializer_list<E> provides access to an array of objects of type const E. [...]

Since initializer lists are collections of const elements, the cbegin() and cend() functions would actually do the exact same thing that begin() and end() do.

In fact, iterator and const_iterator are both defined as pointers to constant elements of the initializer list's value type, so it's arguable whether it is the case that begin() and end() always return const_iterator (as you assume), or whether they always return iterator.

This is how Paragraph 18.9/1 of the C++11 Standard defines the initializer_list class template: