Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are std::begin() and std::end() overloaded for std::initializer_list in C++11?

In C++11 (quoting N3337), std::begin() and std::end() are specified as (§24.7 [iterator.range]/p2-3)

template <class C> auto begin(C& c) -> decltype(c.begin());
template <class C> auto begin(const C& c) -> decltype(c.begin());

2 Returns: c.begin().

template <class C> auto end(C& c) -> decltype(c.end());
template <class C> auto end(const C& c) -> decltype(c.end());

3 Returns: c.end().

std::initializer_list, however, provides its own overloads for these functions (§18.9.3 [support.initlist.range]):

template<class E> const E* begin(initializer_list<E> il) noexcept;

1 Returns: il.begin().

template<class E> const E* end(initializer_list<E> il) noexcept;

2 Returns: il.end().

It seems that these overloads don't do anything beyond the base template, other than (1) having a noexcept specification and (2) taking their parameter by value. However, copying an initializer_list does nothing special (it just copies a pair of pointers or something equally lightweight), so (2) creates no difference in behavior. Moreover, the begin() and end() member functions of many standard containers are also noexcept, yet no overloads of std::begin()/std::end() are specified for those containers, so it seems unlikely the committee specified these overloads just for (1). Why, then, are these overloads provided?

like image 253
T.C. Avatar asked Aug 09 '14 05:08

T.C.


1 Answers

This is explained in N2930, which proposed the change to add the overloads in question. Emphasis mine:

Summary of proposed changes

  • Specify range-based for statements without the use of concepts, using argument-dependent lookup of begin and end (which always includes those begin and end functions in namespace std) to provide the iterator to the beginning and ending of the sequence.
  • Specify range-based for statements so that arrays and initializer lists have no dependencies on <iterator>.
  • Refactor <initializer_list> so that it as no dependencies on other headers and includes no other headers.
  • Specify the library headers that are to #include <initializer_list>.

It seems like they didn't explain why they wanted <initializer_list> to have no dependency on <iterator>, but I think a reasonable guess is that the former is supposed to be available in a freestanding implementation whereas the latter might not be (Table 16, §17.6.1.3)

like image 88
Brian Bi Avatar answered Nov 02 '22 07:11

Brian Bi