Title
Absence of global functions cbegin/cend
Status
c++14
Section
[iterator.synopsis] [iterator.range]
Submitter
Dmitry Polukhin

Created on 2012-01-23.00:00:00 last changed 123 months ago

Messages

Date: 2013-04-18.22:58:13

Proposed resolution:

This wording is relative to N3485.

  1. In [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));
    }
    
  2. At the end of [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).

Date: 2013-04-15.00:00:00

[ 2013-04-18, Bristol ]

Date: 2013-04-14.00:00:00

[ 2013-04-14 STL provides rationale and improved wording ]

Step 1: Implement std::cbegin/cend() by calling std::begin/end(). This has numerous advantages:

  • It automatically works with arrays, which is the whole point of these non-member functions.
  • It works with C++98/03-era user containers, written before cbegin/cend() members were invented.
  • It works with initializer_list, which is extremely minimal and lacks cbegin/cend() members.
  • [container.requirements.general] guarantees that this is equivalent to calling 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 [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.

  1. In [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]);
    }
    
  2. In [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.

Date: 2012-02-27.20:05:44

[ 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.

Date: 2012-01-23.00:00:00

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.

History
Date User Action Args
2014-02-20 13:20:35adminsetstatus: wp -> c++14
2013-04-25 19:07:07adminsetstatus: voting -> wp
2013-04-19 21:44:50adminsetstatus: ready -> voting
2013-04-18 22:58:13adminsetmessages: + msg6451
2013-04-18 22:58:13adminsetstatus: open -> ready
2013-04-13 15:51:38adminsetmessages: + msg6446
2012-02-27 20:05:44adminsetmessages: + msg6042
2012-02-27 20:05:44adminsetstatus: new -> open
2012-02-05 15:54:48adminsetmessages: + msg5990
2012-01-23 00:00:00admincreate