cbegin/cend
Section: 24.2 [iterator.synopsis], 24.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:
cbegin/cend()
members were invented.initializer_list
, which is extremely minimal and lacks cbegin/cend()
members.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 24.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 24.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 24.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 24.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)
.