<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html><head>


  <meta http-equiv="Content-Language" content="en-us">

  <meta name="GENERATOR" content="Microsoft FrontPage 5.0">

  <meta name="ProgId" content="FrontPage.Editor.Document">

  <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">

  <title>Just Works</title>

  <style type="text/css">
ins {background-color:#A0FFA0}
del {background-color:#FFA0A0}
  </style>
</head><body>

<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="496">
  <tr>
    <td>Document number:&nbsp; </td>
    <td> 
N2900=09-0090</td>
  </tr>
  <tr>
    <td>Date:</td>
    <td>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%Y-%m-%d" startspan -->2009-06-16<!--webbot bot="Timestamp" endspan i-checksum="12423" --></td>
  </tr>
  <tr>
    <td>Project:</td>
    <td>Programming Language C++, Library Working Group</td>
  </tr>
  <tr>
    <td>Reply-to:</td>
    <td>Beman Dawes &lt;bdawes at acm.org&gt;</td>
  </tr>
</table>



<h1>Ensuring Certain C++0x Features &quot;just work&quot; - Revision 1<br>
<font size="5">or,</font><b><font size="5"> addressing CD1 comments UK 78 and UK 
79</font></b></h1>



<p><a href="#Introduction">Introduction</a><br>
<a href="#Revision-history">Revision history</a><br>
<a href="#Summary">Summary of proposed changes</a><br>
<a href="#FAQ">FAQ</a><br>
&nbsp;&nbsp;&nbsp; <a href="#why-not-include-iterator-concepts">Why not also 
implicitly <code>#include &lt;iterator_concepts&gt;</code>?</a><br>
<a href="#discussion">Additional discussion</a><br>
<a href="#Proposed-wording">Proposed wording</a><br>
<a href="#Acknowledgements">Acknowledgements</a></p>



<h2><a name="Introduction">Introduction</a></h2>



<p>CD1 comments UK 78 and UK 79 essentially ask that the range-based <i>for</i> 
statement &quot;just work&quot;. Consider the range-based <i>for</i> example given in the 
WP:</p>



<blockquote>
  <p>[ <i>Example:</i></p>
  <blockquote>
    <pre>int array[5] = { 1, 2, 3, 4, 5 };
for (int&amp; x : array)
  x *= 2;</pre>
  </blockquote>
  <p><i>end example</i> ]</p>
</blockquote>
<p>As the WP is currently specified, this example will not compile!&nbsp; It is 
missing:</p>
<blockquote>
  <pre>#include &lt;iterator_concepts&gt;</pre>
</blockquote>
<p>Independent of UK 78/79, a lengthy discussion of range-based <i>for</i> loops 
over arrays on the C++ committee's library reflector&nbsp;found a number of LWG members who 
believe the array case should &quot;just-work&quot; without having to include <code>&lt;iterator_concepts&gt;</code>. 
This is seen as similar to:</p>


<blockquote>
  <pre>... new int ...         // no need for &lt;new&gt;<br>... sizeof(MyType) ...  // no need for &lt;cstddef&gt; to get std::size_t<br>... = nullptr;          // no need for &lt;cstddef&gt; to get nullptr</pre>
</blockquote>


<p>As Peter Dimov said in message c++std-lib-23406:</p>


<blockquote>


<p>It is precisely the required inclusion of <code>&lt;iterator_concepts&gt;</code> that makes 
arrays a special case ... For all other types, the fact that I can 
use the type at all means that I can use it in a [range-based] for-loop as well (because 
the header that defines the type would include <code>&lt;iterator_concepts&gt;</code> for me).</p>


<p>Arrays, however, are available without an #include, so the [range-based] for-loop 
should also be available; the alternative is an inconsistency, a special case 
from the user point of view (not from specification point of view, but this is 
an implementation detail as far as the user is concerned).</p>


</blockquote>


<p>UK 79 also mentions the case of initializer lists. An example comes from 
Bjarne Stroustrup's <a href="http://www.research.att.com/~bs/C++0xFAQ.html">
C++0x FAQ</a>:</p>


<blockquote>
  <pre>for (const auto x : { 1,2,3,5,8,13,21,34 })...;</pre>
</blockquote>
<p>For this to compile given the current WP wording, both <code>&lt;initializer_list&gt;</code> and <code>
&lt;iterator_concepts&gt;</code> must be included. So again, code that should 
&quot;just-work&quot; because it need rely only on features of the core language doesn't work 
without explicit #includes of library headers.</p>


<p>This proposal, together with library issue
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#1001">1001</a>, 
addresses all of the above concerns, and resolves the CD1 UK 78 and UK 79 
comments.</p>


<h2><a name="Summary">Summary</a> of proposed changes</h2>


<ul>
  <li>Implicitly include <code>&lt;initializer_list&gt;</code> in all translation 
  units. This allows <code>std::initializer_list</code> to &quot;just work&quot;, and 
  reflects its special role as part of the core language.<br>
&nbsp;</li>
  <li>Refactor <code>&lt;initializer_list&gt;</code> so that it as no dependencies on 
  other headers and includes no other headers. This minimizes the cost of 
  including it in all translation units.<br>
&nbsp;</li>
  <li>Specify range-based for statements so that arrays and initializer lists 
  have no dependencies on <code>&lt;iterator_concepts&gt;</code> and so do not require users to include 
  headers (unless, of course, the types of 
  objects being iterated over require headers). Header <code>&lt;iterator_concepts&gt;</code> 
  is still required for uses of <code>std::Range</code>.<br>
&nbsp;</li>
  <li>Tweak [res.on.headers] wording for header inclusion so that a header may 
  be specified as including no other headers.<br>
&nbsp;</li>
  <li>Tweak [dcl.init.list] Initializer list wording to reflect the other 
  changes.</li>
</ul>


<h2><a name="Revision-history">Revision history</a></h2>


<p><b>N2900 - Revision 1.</b> Changed &quot;possibly 
cv-qualified&quot; to &quot;possibly const-qualified&quot; in two places to ensure that 
behavior is the same regardless of whether or not <code>&lt;iterator_concepts&gt;</code> 
is included. Suggested by Daniel Krgler. </p>


<p><b>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2872.html">
N2872</a></b> Initial proposal.</p>


<h2><a name="FAQ">FAQ</a></h2>


<h3><a name="why-not-include-iterator-concepts"></a>Why not also implicitly <code>#include &lt;iterator_concepts&gt;</code>?</h3>


<p>Header <code>&lt;iterator_concepts&gt;</code> has a dependency on header <code>
&lt;concepts&gt;</code>, so both would have to be included. That's an unacceptably 
large cost for the many translation units that will need neither header. It also 
unnecessarily couples the core language to portions of the library not actually 
required for language support, and that is considered a poor design practice. 
With the proposed resolution of library issue
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#1001">1001</a>, <code>&lt;iterator_concepts&gt;</code> 
never has to be explicitly 
included for the range-based <i>for</i> statement to work with standard library types.</p>


<p>In contrast, <code>&lt;iterator_list&gt;</code> as modified by this proposal is very small, 
has no dependencies, contains nothing except template <code>initializer_list</code>, 
is tightly coupled to core language support, and is critical to the range-based 
for statement &quot;just working&quot;.</p>


<p>Implicitly including <code>&lt;iterator_concepts&gt;</code> 
has been looked at numerous times by multiple C++ committee sub-groups and soundly rejected each time.</p>


<h2>Additional <a name="discussion">discussion</a></h2>


<p>Gabriel Dos Reis in c++std-lib-23383:</p>


<blockquote>


<p>We don't need &lt;iterator_concepts&gt; to tell us what</p>


<blockquote>
  <pre>&nbsp; &nbsp;for (v: ary) {<br>&nbsp; &nbsp; &nbsp;// ...<br>&nbsp; &nbsp;}</pre>
</blockquote>

<p>does when 'ary' is a C-array. &nbsp;<code>&lt;iterator_concepts&gt;</code> is not part of the model. 
&nbsp;It is an implementation detail that should not leak.</p>


</blockquote>


<p>Peter Dimov in message c++std-lib-23408 points out:</p>


<blockquote>


<p>... the observable behavior of the for-loop [with the proposed change] always 
matches its description in terms of the Range concept (it always "uses" the 
Range concept). The fact that 'for' on a C array does not require the [explicit] 
definition of Range is an implementation detail and not detectable. You can't 
add a concept map without also having Range defined (right?), so there is no way 
you can observe the difference.</p>


</blockquote>


<p>UK 79 comment:</p>


<blockquote>


<p>The definition of for (for-range-declaration : expression) statement is 
expanded in terms which require a Range concept, and the program is ill-formed 
if <code>&lt;iterator_concepts&gt;</code> isn't included. For users, iterating through 
old-fashioned arrays, this is a sledge-hammer to crack a nut and compares poorly 
with other languages. It's also not possible to implement this without adversely 
impacting the freestanding definition in 17.6.2.4.</p>


</blockquote>


<h2><a name="Proposed-wording">Proposed wording</a></h2>


<p><i>Text to be removed is shown in 
<span style="background-color: #FFA0A0; text-decoration:line-through">red</span>, 
text to be added is shown in <span style="background-color: #A0FFA0">green</span>.&nbsp; 
Underbars are not shown for additions because the many underscores in the 
affected text become unreadable. Changes shown in
<span style="background-color: #CCCCCC">gray</span> are editorial changes 
recommended for consideration by the project editor.</i></p>


<p><i>Change 18.9 [support.initlist], Initializer lists, paragraph 1,, as indicated:</i></p>


<blockquote>
  <p>The header <code>&lt;initializer_list&gt;</code> defines one type. <span style="background-color: #A0FFA0">Header </span><code>
  <span style="background-color: #A0FFA0">&lt;initializer_list&gt;</span></code><span style="background-color: #A0FFA0"> 
  shall be implicitly included at the start of each translation unit. Header </span><code>
  <span style="background-color: #A0FFA0">&lt;initializer_list&gt;</span></code><span style="background-color: #A0FFA0"> 
  shall not include other C++ standard library headers. [<i>Note:</i> Thus <code>#include </code></span><code>
  <span style="background-color: #A0FFA0">&lt;initializer_list&gt;</span></code><span style="background-color: #A0FFA0"> has no effect. <i>--end note</i>]</span></p>
</blockquote>


<p><i>Change 18.9 [support.initlist], Initializer lists, 
Header &lt;initializer_list&gt; synopsis, as indicated:</i></p>


<blockquote>
  <pre>namespace std {
  template&lt;ObjectType E&gt; class initializer_list {
  public:
    typedef E value_type;
    typedef const E&amp; reference;
    typedef const E&amp; const_reference;
    typedef size_t size_type;

    typedef const E* iterator;
    typedef const E* const_iterator;

    initializer_list();

    size_t size() const; // number of elements
    const E* begin() const; // first element
    const E* end() const; // one past the last element
  };

<strike><span style="background-color: #FFA0A0">  template&lt;typename T&gt;
  concept_map Range&lt;initializer_list&lt;T&gt; &gt; see below;

  template&lt;typename T&gt;
  concept_map Range&lt;const initializer_list&lt;T&gt; &gt; see below;</span></strike></pre>
  <pre><span style="background-color: #FFA0A0"></span>}</pre>
</blockquote>
<p><i>Add initializer_list concept maps to 24.2 [iterator.concepts], Iterator 
concepts, Header &lt;iterator_concepts&gt; synopsis:</i></p>


<blockquote>
  <pre>namespace std {
  concept Iterator&lt;typename X&gt; see below;

  // 24.2.2, input iterators:
  concept InputIterator&lt;typename X&gt; see below;

  // 24.2.3, output iterators:
  auto concept OutputIterator&lt;typename X, typename Value&gt; see below;

  // 24.2.4, forward iterators:
  concept ForwardIterator&lt;typename X&gt; see below;

  // 24.2.5, bidirectional iterators:
  concept BidirectionalIterator&lt;typename X&gt; see below;

  // 24.2.6, random access iterators:
  concept RandomAccessIterator&lt;typename X&gt; see below;
  template&lt;ObjectType T&gt; concept_map RandomAccessIterator&lt;T*&gt; see below;
  template&lt;ObjectType T&gt; concept_map RandomAccessIterator&lt;const T*&gt; see below;

  // 24.2.7, shuffle iterators:
  auto concept ShuffleIterator&lt;typename X&gt; see below;

  // 24.2.8, ranges:
  concept Range&lt;typename T&gt; see below;

  template&lt;class T, size_t N&gt;
    concept_map Range&lt;T[N]&gt; see below;

<span style="background-color: #A0FFA0">  template&lt;typename T&gt;
  </span><span style="background-color: #A0FFA0">concept_map</span><span style="background-color: #A0FFA0"> Range&lt;</span><span style="background-color: #A0FFA0">initializer_list</span><span style="background-color: #A0FFA0">&lt;T&gt; &gt; see below;

  template&lt;typename T&gt;
  </span><span style="background-color: #A0FFA0">concept_map</span><span style="background-color: #A0FFA0"> Range&lt;const </span><span style="background-color: #A0FFA0">initializer_list</span><span style="background-color: #A0FFA0">&lt;T&gt; &gt; see below;
</span>}</pre>
</blockquote>
  <p><i>Move the two concept maps below from 18.9.3 [support.initlist.concept], 
  Initializer_list concept maps, to the end of section 24.2.8 
  [iterator.concepts.range] Ranges:</i></p>
<blockquote>
  <pre>template&lt;typename T&gt;
concept_map Range&lt;initializer_list&lt;T&gt; &gt; {
  typedef const T* iterator;

  iterator begin(initializer_list&lt;T&gt; r) { return r.begin(); }
  iterator end(initializer_list&lt;T&gt; r) { return r.end(); }
}

template&lt;typename T&gt;
concept_map Range&lt;const initializer_list&lt;T&gt; &gt; {
  typedef const T* iterator;

  iterator begin(initializer_list&lt;T&gt; r) { return r.begin(); }
  iterator end(initializer_list&lt;T&gt; r) { return r.end(); }
}</pre>
</blockquote>
<p><i>Change 6.5.4 [stmt.ranged], The range-based for statement, as indicated: </i>
</p>


<blockquote>


<p>The range-base<span style="background-color: #CCCCCC; text-decoration:underline">d</span> for statement </p>


  <blockquote>


<p><code>for (</code> <i>for-range-declaration </i><code>:</code><i> expression</i>
<code>)</code> <i>statement</i></p>


  </blockquote>


<p>&nbsp;is equivalent to</p>


  <blockquote>
    <pre>{
auto &amp;&amp; __range = ( <i><span style="background-color: #CCCCCC">expression</span></i> );
for ( auto __begin = <strike><span style="background-color: #FFA0A0">std::Range&lt;_RangeT&gt;::begin(__range)</span></strike> <b><i><span style="background-color: #A0FFA0">begin-expr</span></i></b>,
__end = <strike><span style="background-color: #FFA0A0">std::Range&lt;_RangeT&gt;::end(__range)</span></strike> <b><i><span style="background-color: #A0FFA0">end-expr</span></i></b>;
__begin != __end;
++__begin ) {
  for-range-declaration = *__begin;
  statement
  }
}</pre>
  </blockquote>
  <p>where <code>__range</code>, <code>__begin</code>, and <code>__end</code> are 
  variables defined for exposition only, 
  <span style="background-color: #FFA0A0; text-decoration:line-through">and</span> <code>_RangeT</code> is the type 
  of <span style="text-decoration: line-through; background-color: #CCCCCC">the</span><span style="background-color: #CCCCCC">
  </span><i><code><span style="background-color: #CCCCCC">expression</span></code></i><span style="background-color: #A0FFA0">, and </span> <b><i>
  <code><span style="background-color: #A0FFA0">begin-expr</span></code></i></b><span style="background-color: #A0FFA0"> and
  </span> <b><i><code><span style="background-color: #A0FFA0">end-expr</span></code></i></b><span style="background-color: #A0FFA0"> are determined 
  as follows:</span></p>
  <ul>
    <li>If the header <code>&lt;iterator_concepts&gt;</code> ([iterator.concepts])
    <span style="text-decoration: line-through; background-color: #FFA0A0">is not</span>
    <span style="background-color: #A0FFA0">has been</span> included prior to 
    <span style="text-decoration: line-through; background-color: #FFA0A0">a</span>
    <span style="background-color: #A0FFA0">this</span> use of the range-based 
    for statement, <b><i><code>
    <span style="background-color: #A0FFA0">begin-expr</span></code></i></b><span style="background-color: #A0FFA0"> and
    </span> 
    <b><i><code><span style="background-color: #A0FFA0">end-expr</span></code></i></b><span style="background-color: #A0FFA0"> are
    </span><code><span style="background-color: #A0FFA0">std::Range&lt;_RangeT&gt;::begin(__range)</span></code><span style="background-color: #A0FFA0"> and
    </span><code><span style="background-color: #A0FFA0">std::Range&lt;_RangeT&gt;::end(__range)</span></code><span style="background-color: #A0FFA0">, 
    respectively</span>. <br>
&nbsp;</li>
    <li><span style="background-color: #A0FFA0">Otherwise, if </span> <code>
    <span style="background-color: #A0FFA0">_RangeT</span></code><span style="background-color: #A0FFA0"> 
    is a possibly const-qualified 
    array of a complete type,
    </span> <b><i><code><span style="background-color: #A0FFA0">begin-expr</span></code></i></b><span style="background-color: #A0FFA0"> and
    </span> 
    <b><i><code><span style="background-color: #A0FFA0">end-expr</span></code></i></b><span style="background-color: #A0FFA0"> are
    </span> <code><span style="background-color: #A0FFA0">__range</span></code><span style="background-color: #A0FFA0"> and
    </span> 
  <code><span style="background-color: #A0FFA0">__range+__bound</span></code><span style="background-color: #A0FFA0">, respectively, where
    </span> 
  <code><span style="background-color: #A0FFA0">__bound</span></code><span style="background-color: #A0FFA0"> is the array bound.</span><br>
&nbsp;</li>
    <li><span style="background-color: #A0FFA0">Otherwise, if </span> <code>
    <span style="background-color: #A0FFA0">_RangeT</span></code><span style="background-color: #A0FFA0"> is 
    a possibly const-qualified&nbsp;
    </span><code><span style="background-color: #A0FFA0">std::initializer_list</span></code><span style="background-color: #A0FFA0">,
    </span> <b><i><code><span style="background-color: #A0FFA0">begin-expr</span></code></i></b><span style="background-color: #A0FFA0"> and
    </span> 
    <b><i><code><span style="background-color: #A0FFA0">end-expr</span></code></i></b><span style="background-color: #A0FFA0"> are
    </span><code><span style="background-color: #A0FFA0">__range.begin()</span></code><span style="background-color: #A0FFA0"> and
    </span><code><span style="background-color: #A0FFA0">__range.end()</span></code><span style="background-color: #A0FFA0">, 
    respectively. [</span><i><span style="background-color: #A0FFA0">Note:</span></i><span style="background-color: #A0FFA0"> 
    The template </span><code><span style="background-color: #A0FFA0">
    std::initializer_list</span></code><span style="background-color: #A0FFA0"> 
    is predefined ([</span><span style="background-color: #A0FFA0">support.initlist</span><span style="background-color: #A0FFA0">]).
    </span><i><span style="background-color: #A0FFA0">--end note</span></i><span style="background-color: #A0FFA0">]</span><br>
&nbsp;</li>
    <li><span style="background-color: #A0FFA0">Otherwise</span>, the program is 
    ill-formed.<br>
&nbsp;</li>
</ul>
    <p>[ <i>Example:</i></p>
    <blockquote>
      <pre>int array[5] = { 1, 2, 3, 4, 5 };
for (int&amp; x : array)
  x *= 2;</pre>
    </blockquote>
    <p><i>end example</i> ]</p>


</blockquote>


<p><i>Change 17.6.4.2 [res.on.headers], Headers, paragraph 1, as indicated:</i></p>


<blockquote>


<p>A C++ header may include other C++ headers
<span style="background-color: #A0FFA0">unless otherwise specified</span>.</p>


</blockquote>


<p><i>Change 8.5.4 [dcl.init.list],&nbsp; List-initialization, paragraph 3, as 
indicated:</i></p>


<blockquote>


<p>A constructor is an initializer-list constructor if its first parameter is of 
type <code>std::initializer_list&lt;E&gt;</code> ([support.initlist]) or reference to possibly cv-qualified 
<code>std::initializer_list&lt;E&gt;</code> for some type <code>E</code>, and either there are no other 
parameters or else all other parameters have default arguments (8.3.6). [ Note: 
Initializer-list constructors are favored over other constructors in 
list-initialization (13.3.1.7).end note ] <strike> 
<span style="background-color: #FFA0A0">The template <code>std::initializer_list</code> is 
not predefined; if the header <code>&lt;</code></span><code><span style="background-color: #FFA0A0">initializer_list</span></code><span style="background-color: #FFA0A0"><code>&gt;</code> is not included prior to a use 
of <code>std::initializer_list</code>  even an implicit use in which the type is not named 
(7.1.6.4)  the program is ill-formed.</span></strike>
<span style="background-color: #A0FFA0">[</span><i><span style="background-color: #A0FFA0">Note:</span></i><span style="background-color: #A0FFA0"> 
The template </span><code><span style="background-color: #A0FFA0">
std::initializer_list</span></code><span style="background-color: #A0FFA0"> is 
predefined ([support.initlist]). </span><i>
<span style="background-color: #A0FFA0">--end note</span></i><span style="background-color: #A0FFA0">]</span></p>


</blockquote>


<h2><a name="Acknowledgements">Acknowledgements</a></h2>

<p>This proposal parallels
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2814.pdf">
N2814</a>, <i>Fixing Freestanding</i>, by Martin Tasker and Jan van Bergen, 
as regards range-based for statements and header <code>&lt;initializer_list&gt;</code>. 
Martin and Jan provided helpful suggestions for this proposal.</p>

<p>James Widman identified several deficiencies in drafts of this proposal and 
provided fixes for them.</p>
<p>Steve Adamczyk, Alberto Ganesh Barbati, Walter E Brown, Gabriel Dos Reis, Doug Gregor, Daniel Krgler, Jens Maurer, Thorsten Ottosen, 
Bjarne Stroustrup, Herb Sutter, 
and James Widman participated in discussions, reviewed drafts, and suggested 
improvements.</p>
<hr>


</body></html>