This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++14 status.
Section: 25.2 [iterator.synopsis], 25.7 [iterator.range] Status: C++14 Submitter: Dmitry Polukhin Opened: 2012-01-23 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [iterator.synopsis].
View all issues with C++14 status.
Discussion:
All standard containers support cbegin/cend member functions but corresponding global functions are missing. Proposed resolution it to add global cbegin/cend functions by analogy with global begin/end functions. This addition will unify things for users.
[2012, Kona]
STL: Range-based for loops do not use global begin/end (anymore).
Alisdair: We will have to make sure these will be available through many headers.
STL: Do this, including r and cr. This won't add any additional work.
Matt: Users will find it strange if these are not all available.
Alisdair: Should we have these available everywhere begin/end are available?
Marshall: Yes. Not any extra work.
Howard: Adding all of these means we need all of <iterator>.
STL: We already need it all.
Matt: We have to be careful what we are requiring if we include the r versions.
Jeffrey: If we include r, should they adapt if the container does not define reverse iteration?
STL: No. No special behavior. Should fail to compile. Up to user to add the reverse code--it's easy.
Howard: Anyway it will SFINAE out.
Alisdair: Error messages due to SFINAE are harder to understand than simple failure to compile.
STL: Agrees that SFINAE makes error messages much worse.
Action: STL to provide additional wording for the r variants. Move to Review once that wording is availalbe.
[ 2013-04-14 STL provides rationale and improved wording ]
Step 1: Implement std::cbegin/cend() by calling std::begin/end(). This has numerous advantages:
Step 2: Like std::begin/end(), implement std::rbegin/rend() by calling c.rbegin/rend(). Note that C++98/03 had the Reversible Container Requirements.
Step 3: Also like std::begin/end(), provide overloads of std::rbegin/rend() for arrays.
Step 4: Provide overloads of std::rbegin/rend() for initializer_list, because it lacks rbegin/rend() members. These overloads follow 17.10.5 [support.initlist.range]'s signatures. Note that because these overloads return reverse_iterator, they aren't being specified in <initializer_list>.
Step 5: Like Step 1, implement std::crbegin/crend() by calling std::rbegin/rend().
Original wording saved here:
This wording is relative to N3337.
In 25.2 [iterator.synopsis], header iterator synopsis, add the following declarations:
namespace std { […] // 24.6.5, range access: template <class C> auto begin(C& c) -> decltype(c.begin()); template <class C> auto begin(const C& c) -> decltype(c.begin()); template <class C> auto end(C& c) -> decltype(c.end()); template <class C> auto end(const C& c) -> decltype(c.end()); template <class C> auto cbegin(const C& c) -> decltype(c.cbegin()); template <class C> auto cend(const C& c) -> decltype(c.cend()); template <class T, size_t N> T* begin(T (&array)[N]); template <class T, size_t N> T* end(T (&array)[N]); template <class T, size_t N> const T* cbegin(T (&array)[N]); template <class T, size_t N> const T* cend(T (&array)[N]); }In 25.7 [iterator.range] after p5 add the following series of paragraphs:
template <class C> auto cbegin(const C& c) -> decltype(c.cbegin());-?- Returns: c.cbegin().
template <class C> auto cend(const C& c) -> decltype(c.cend());-?- Returns: c.cend().
template <class T, size_t N> const T* cbegin(T (&array)[N]);-?- Returns: array.
template <class T, size_t N> const T* cend(T (&array)[N]);-?- Returns: array + N.
[2013-04-18, Bristol]
Proposed resolution:
This wording is relative to N3485.
In 25.2 [iterator.synopsis], header iterator synopsis, add the following declarations:
namespace std { […] // 24.6.5, range access: template <class C> auto begin(C& c) -> decltype(c.begin()); template <class C> auto begin(const C& c) -> decltype(c.begin()); template <class C> auto end(C& c) -> decltype(c.end()); template <class C> auto end(const C& c) -> decltype(c.end()); template <class T, size_t N> T* begin(T (&array)[N]); template <class T, size_t N> T* end(T (&array)[N]); template <class C> auto cbegin(const C& c) -> decltype(std::begin(c)); template <class C> auto cend(const C& c) -> decltype(std::end(c)); template <class C> auto rbegin(C& c) -> decltype(c.rbegin()); template <class C> auto rbegin(const C& c) -> decltype(c.rbegin()); template <class C> auto rend(C& c) -> decltype(c.rend()); template <class C> auto rend(const C& c) -> decltype(c.rend()); template <class T, size_t N> reverse_iterator<T*> rbegin(T (&array)[N]); template <class T, size_t N> reverse_iterator<T*> rend(T (&array)[N]); template <class E> reverse_iterator<const E*> rbegin(initializer_list<E> il); template <class E> reverse_iterator<const E*> rend(initializer_list<E> il); template <class C> auto crbegin(const C& c) -> decltype(std::rbegin(c)); template <class C> auto crend(const C& c) -> decltype(std::rend(c)); }
At the end of 25.7 [iterator.range], add:
template <class C> auto cbegin(const C& c) -> decltype(std::begin(c));-?- Returns: std::begin(c).
template <class C> auto cend(const C& c) -> decltype(std::end(c));-?- Returns: std::end(c).
template <class C> auto rbegin(C& c) -> decltype(c.rbegin()); template <class C> auto rbegin(const C& c) -> decltype(c.rbegin());-?- Returns: c.rbegin().
template <class C> auto rend(C& c) -> decltype(c.rend()); template <class C> auto rend(const C& c) -> decltype(c.rend());-?- Returns: c.rend().
template <class T, size_t N> reverse_iterator<T*> rbegin(T (&array)[N]);-?- Returns: reverse_iterator<T*>(array + N).
template <class T, size_t N> reverse_iterator<T*> rend(T (&array)[N]);-?- Returns: reverse_iterator<T*>(array).
template <class E> reverse_iterator<const E*> rbegin(initializer_list<E> il);-?- Returns: reverse_iterator<const E*>(il.end()).
template <class E> reverse_iterator<const E*> rend(initializer_list<E> il);-?- Returns: reverse_iterator<const E*>(il.begin()).
template <class C> auto crbegin(const C& c) -> decltype(std::rbegin(c));-?- Returns: std::rbegin(c).
template <class C> auto crend(const C& c) -> decltype(std::rend(c));-?- Returns: std::rend(c).