<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2128: Absence of global functions cbegin&#47;cend</title>
<meta property="og:title" content="Issue 2128: Absence of global functions cbegin&#47;cend">
<meta property="og:description" content="C++ library issue. Status: C++14">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2128.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++14">C++14</a> status.</em></p>
<h3 id="2128"><a href="lwg-defects.html#2128">2128</a>. Absence of global functions <code>cbegin&#47;cend</code></h3>
<p><b>Section:</b> 24.2 <a href="https://wg21.link/iterator.synopsis">[iterator.synopsis]</a>, 24.7 <a href="https://wg21.link/iterator.range">[iterator.range]</a> <b>Status:</b> <a href="lwg-active.html#C++14">C++14</a>
 <b>Submitter:</b> Dmitry Polukhin <b>Opened:</b> 2012-01-23 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#iterator.synopsis">issues</a> in [iterator.synopsis].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++14">C++14</a> status.</p>
<p><b>Discussion:</b></p>

<p>
All standard containers support <code>cbegin&#47;cend</code> member functions but corresponding global functions are 
missing. Proposed resolution it to add global <code>cbegin&#47;cend</code> functions by analogy with global <code>begin&#47;end</code> 
functions. This addition will unify things for users.
</p>

<p><i>[2012, Kona]</i></p>


<p>STL: Range-based for loops do not use global <code>begin</code>/<code>end</code> (anymore).</p>
<p>Alisdair: We will have to make sure these will be available through many headers.</p>
<p>STL: Do this, including <code>r</code> and <code>cr</code>. This won't add any additional work.</p>
<p>Matt: Users will find it strange if these are not all available.</p>
<p>Alisdair: Should we have these available everywhere begin/end are available?</p>
<p>Marshall: Yes. Not any extra work.</p>
<p>Howard: Adding all of these means we need all of <code>&lt;iterator></code>.</p>
<p>STL: We already need it all.</p>
<p>Matt: We have to be careful what we are requiring if we include the <code>r</code> versions.</p>
<p>Jeffrey: If we include <code>r</code>, should they adapt if the container does not define reverse iteration?</p>
<p>STL: No. No special behavior. Should fail to compile. Up to user to add the reverse code--it's easy.</p>
<p>Howard: Anyway it will SFINAE out.</p>
<p>Alisdair: Error messages due to SFINAE are harder to understand than simple failure to compile.</p>
<p>STL: Agrees that SFINAE makes error messages much worse.</p>

<p>
Action: STL to provide additional wording for the <code>r</code> variants.
Move to Review once that wording is availalbe.
</p>

<p><i>[
2013-04-14 STL provides rationale and improved wording
]</i></p>


<p>Step 1: Implement <code>std::cbegin/cend()</code> by calling <code>std::begin/end()</code>. This has numerous advantages:</p>
<ul>
<li>It automatically works with arrays, which is the whole point of these non-member functions.</li>
<li>It works with C++98/03-era user containers, written before <code>cbegin/cend()</code> members were invented.</li>
<li>It works with <code>initializer_list</code>, which is extremely minimal and lacks <code>cbegin/cend()</code> members.</li>
<li>23.2.2 <a href="https://wg21.link/container.requirements.general">[container.requirements.general]</a> guarantees that this is equivalent to calling cbegin/cend() members.</li>
</ul>
<p>Step 2: Like <code>std::begin/end()</code>, implement <code>std::rbegin/rend()</code> by calling <code>c.rbegin/rend()</code>.  
Note that C++98/03 had the <code>Reversible Container Requirements</code>.</p>
<p>Step 3: Also like <code>std::begin/end()</code>, provide overloads of <code>std::rbegin/rend()</code> for arrays.</p>
<p>Step 4: Provide overloads of <code>std::rbegin/rend()</code> for <code>initializer_list</code>, because it lacks 
<code>rbegin/rend()</code> members. These overloads follow 17.11.5 <a href="https://wg21.link/support.initlist.range">[support.initlist.range]</a>'s signatures. Note that 
because these overloads return <code>reverse_iterator</code>, they aren't being specified in <code>&lt;initializer_list&gt;</code>.</p>
<p>Step 5: Like Step 1, implement <code>std::crbegin/crend()</code> by calling <code>std::rbegin/rend()</code>.</p>

<p>Original wording saved here:</p>
<blockquote class="note">
<p>This wording is relative to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf">N3337</a>.</p>

<ol>
<li><p>In 24.2 <a href="https://wg21.link/iterator.synopsis">[iterator.synopsis]</a>, header iterator synopsis, add the following declarations:</p>

<blockquote><pre>
namespace std {
  [&hellip;]
  <i>// 24.6.5, range access:</i>
  template &lt;class C&gt; auto begin(C&amp; c) -> decltype(c.begin());
  template &lt;class C&gt; auto begin(const C&amp; c) -> decltype(c.begin());
  template &lt;class C&gt; auto end(C&amp; c) -> decltype(c.end());
  template &lt;class C&gt; auto end(const C&amp; c) -> decltype(c.end());
  <ins>template &lt;class C&gt; auto cbegin(const C&amp; c) -> decltype(c.cbegin());</ins>
  <ins>template &lt;class C&gt; auto cend(const C&amp; c) -> decltype(c.cend());</ins>
  template &lt;class T, size_t N&gt; T* begin(T (&amp;array)[N]);
  template &lt;class T, size_t N&gt; T* end(T (&amp;array)[N]);
  <ins>template &lt;class T, size_t N&gt; const T* cbegin(T (&amp;array)[N]);</ins>
  <ins>template &lt;class T, size_t N&gt; const T* cend(T (&amp;array)[N]);</ins>
}
</pre></blockquote>
</li>

<li><p>In 24.7 <a href="https://wg21.link/iterator.range">[iterator.range]</a> after p5 add the following series of paragraphs:</p>

<blockquote>
<pre>
<ins>template &lt;class C&gt; auto cbegin(const C&amp; c) -> decltype(c.cbegin());</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>c.cbegin()</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class C&gt; auto cend(const C&amp; c) -> decltype(c.cend());</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>c.cend()</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class T, size_t N&gt; const T* cbegin(T (&amp;array)[N]);</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>array</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class T, size_t N&gt; const T* cend(T (&amp;array)[N]);</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>array + N</code>.</ins>
</p>
</blockquote>
</blockquote>
</li>
</ol>

</blockquote>

<p><i>[2013-04-18, Bristol]</i></p>




<p id="res-2128"><b>Proposed resolution:</b></p>
<p>This wording is relative to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf">N3485</a>.</p>

<ol>
<li><p>In 24.2 <a href="https://wg21.link/iterator.synopsis">[iterator.synopsis]</a>, header iterator synopsis, add the following declarations:</p>

<blockquote><pre>
namespace std {
  [&hellip;]
  <i>// 24.6.5, range access:</i>
  template &lt;class C&gt; auto begin(C&amp; c) -> decltype(c.begin());
  template &lt;class C&gt; auto begin(const C&amp; c) -> decltype(c.begin());
  template &lt;class C&gt; auto end(C&amp; c) -> decltype(c.end());
  template &lt;class C&gt; auto end(const C&amp; c) -> decltype(c.end());
  template &lt;class T, size_t N&gt; T* begin(T (&amp;array)[N]);
  template &lt;class T, size_t N&gt; T* end(T (&amp;array)[N]);
  <ins>template &lt;class C&gt; auto cbegin(const C&amp; c) -> decltype(std::begin(c));</ins>
  <ins>template &lt;class C&gt; auto cend(const C&amp; c) -> decltype(std::end(c));</ins>
  <ins>template &lt;class C&gt; auto rbegin(C&amp; c) -> decltype(c.rbegin());</ins>
  <ins>template &lt;class C&gt; auto rbegin(const C&amp; c) -> decltype(c.rbegin());</ins>
  <ins>template &lt;class C&gt; auto rend(C&amp; c) -> decltype(c.rend());</ins>
  <ins>template &lt;class C&gt; auto rend(const C&amp; c) -> decltype(c.rend());</ins>
  <ins>template &lt;class T, size_t N&gt; reverse_iterator&lt;T*&gt; rbegin(T (&amp;array)[N]);</ins>
  <ins>template &lt;class T, size_t N&gt; reverse_iterator&lt;T*&gt; rend(T (&amp;array)[N]);</ins>
  <ins>template &lt;class E> reverse_iterator&lt;const E*&gt; rbegin(initializer_list&lt;E&gt; il);</ins>
  <ins>template &lt;class E> reverse_iterator&lt;const E*&gt; rend(initializer_list&lt;E&gt; il);</ins>
  <ins>template &lt;class C&gt; auto crbegin(const C&amp; c) -> decltype(std::rbegin(c));</ins>
  <ins>template &lt;class C&gt; auto crend(const C&amp; c) -> decltype(std::rend(c));</ins>
}
</pre></blockquote>
</li>

<li><p>At the end of 24.7 <a href="https://wg21.link/iterator.range">[iterator.range]</a>, add:</p>

<blockquote>
<pre>
<ins>template &lt;class C&gt; auto cbegin(const C&amp; c) -> decltype(std::begin(c));</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>std::begin(c)</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class C&gt; auto cend(const C&amp; c) -> decltype(std::end(c));</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>std::end(c)</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class C&gt; auto rbegin(C&amp; c) -> decltype(c.rbegin());</ins>
<ins>template &lt;class C&gt; auto rbegin(const C&amp; c) -> decltype(c.rbegin());</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>c.rbegin()</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class C&gt; auto rend(C&amp; c) -> decltype(c.rend());</ins>
<ins>template &lt;class C&gt; auto rend(const C&amp; c) -> decltype(c.rend());</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>c.rend()</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class T, size_t N&gt; reverse_iterator&lt;T*&gt; rbegin(T (&amp;array)[N]);</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>reverse_iterator&lt;T*&gt;(array + N)</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class T, size_t N&gt; reverse_iterator&lt;T*&gt; rend(T (&amp;array)[N]);</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>reverse_iterator&lt;T*&gt;(array)</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class E> reverse_iterator&lt;const E*&gt; rbegin(initializer_list&lt;E&gt; il);</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>reverse_iterator&lt;const E*&gt;(il.end())</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class E> reverse_iterator&lt;const E*&gt; rend(initializer_list&lt;E&gt; il);</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>reverse_iterator&lt;const E*&gt;(il.begin())</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class C&gt; auto crbegin(const C&amp; c) -> decltype(std::rbegin(c));</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>std::rbegin(c)</code>.</ins>
</p>
</blockquote>

<pre>
<ins>template &lt;class C&gt; auto crend(const C&amp; c) -> decltype(std::rend(c));</ins>
</pre>
<blockquote>
<p>
<ins>-?- <i>Returns</i>: <code>std::rend(c)</code>.</ins>
</p>
</blockquote>
</blockquote>
</li>
</ol>






</body>
</html>
