<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
  <head>
    <meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
    <title>Selection statements with initializer</title>
    <style type="text/css">
      html { margin: 0; padding: 0; color: black; background-color: white; }
      body { padding: 2em; font-size: medium; font-family: "DejaVu Serif", serif; line-height: 150%; }
      code { font-family: "DejaVu Sans Mono", monospace; color: #006; }

      h1, h2, h3 { margin: 1.5em 0 .75em 0; line-height: 125%; }

      sup, sub { line-height: 0; }

      div.code { white-space: pre-line; font-family: "DejaVu Sans Mono", monospace;
                 border: thin solid #E0E0E0; background-color: #F8F8F8; padding: 1em;
                 border-radius: 4px; }

      div.strictpre { white-space: pre; }

      div.code em { font-family: "DejaVu Serif", serif; }

      table { border-top: 2px solid black; border-bottom: 2px solid black; border-collapse: collapse; margin: 3em auto; }
      thead th { border-bottom: 2px solid black; }
      th, td { text-align: left; padding: 1ex 1ex 1ex 5em; }
      th:first-child, td:first-child { padding-left: 1ex; }

      tr.new td { background-color: #EFE; }
      td.new:after { content: "new!"; font-family: "DejaVu Sans", sans-serif; font-weight: bold; font-size: xx-small;
                     vertical-align: top; top: -1em; right: -1em; position: relative; float: right; color: #090; }

      .docinfo { float: right }
      .docinfo p { margin: 0; text-align:right; }
      .docinfo address { font-style: normal; }

      .quote { display: inline-block; clear: both; margin-left: 1ex;
               border: thin solid #E0E0E0; background-color: #F8F8F8; padding: 1ex; }

      /*  Use DIV[insert] and DIV[delete] if the entire paragraph is added or removed; otherwise
       *  use DIV[modify] and use INS/DEL elements to mark up individual changes.
       */

      div.insert { border-left: thick solid #0A0; border-right: thick solid #0A0; padding: 0 1em; }
      div.modify { border-left: thick solid #999; border-right: thick solid #999; padding: 0 1em; }
      div.delete { border-left: thick solid #A00; border-right: thick solid #A00; padding: 0 1em; }

      del { color: #A00; text-decoration: line-through; }
      ins { color: #090; }
      ins code, del code { color: inherit; }

      .box { border: thin black solid; padding: 2px; }
    </style>
  </head>
  <body>
    <div class="docinfo">
      <p>ISO/IEC JTC1 SC22 WG21 P0305R1</p>
      <p>Date: 2016-06-24</p>
      <p>To: EWG, CWG</p>
      <address>
        Thomas K&ouml;ppe &lt;<a href="mailto:tkoeppe@google.com">tkoeppe@google.com</a>&gt;<br>
      </address>
    </div>

    <h1>Selection statements with initializer</h1>

    <h2>Abstract</h2>

    <p>We propose new versions of the <code>if</code> and <code>switch</code> statements for C++:
      &nbsp; <code>if (<em>init</em>; <em>condition</em>)</code> &nbsp; and &nbsp; <code>switch
      (<em>init</em>; <em>condition</em>)</code>&nbsp;.
      These statements simplify common code patterns and help users keep scopes tight.</p>

    <h2>Contents</h2>
    <!-- fgrep -e "<h2 id=" if2.html | sed -e 's/.*id="\(.*\)">\(.*\)<\/h2>/<li><a href="#\1">\2<\/a><\/li>/g' -->
    <ol>
      <li><a href="#history">Revision history</a></li>
      <li><a href="#beforeafter">Before/After</a></li>
      <li><a href="#proposal">Proposal</a></li>
      <li><a href="#motivation">Motivation</a></li>
      <li><a href="#alternatives">Alternatives</a></li>
      <li><a href="#discussion">Discussion</a></li>
      <li><a href="#impact">Impact on the Standard</a></li>
      <li><a href="#ack">Acknowledgements</a></li>
      <li><a href="#wording">Proposed wording</a></li>
      <li><a href="#constexpr">If constexpr</a></li>
    </ol>

    <h2 id="history">Revision history</h2>

    <ul>
      <li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0305r0.html">P0305R0</a>:
        Initial version (post-Jacksonville mailing), &ldquo;If statement with initializer&rdquo;.</li>
      <li>P0305R1: This version. Change title to &ldquo;Selection statements with initializer&rdquo;.
        Amend the proposal to also extend <code>switch</code> and to support <code>if constexpr</code>
        following EWG guidance.</li>
    </ul>

    <h2 id="beforeafter">Before/After</h2>

    <table>
      <col style="width: 37em">
      <col style="width: 42em">

      <thead>
        <tr><th>Before the proposal</th><th>With the proposal</th></tr>
      </thead>

      <tbody>
        <tr>
          <td><div class="code" style="color: #A00">{
              &nbsp; auto p = m.try_emplace(key, value);
              &nbsp; if (!p.second) {
              &nbsp; &nbsp; FATAL("Element already registered");
              &nbsp; } else {
              &nbsp; &nbsp; process(p.second);
              &nbsp; }
              }</div></td>
          <td><div class="code" style="color: #0A0">if (auto p = m.try_emplace(key, value); !p.second) {
              &nbsp; FATAL("Element already registered");
              } else {
              &nbsp; process(p.second);
              }</div></td>
        </tr>

        <tr>
          <td><div class="code" style="color: #A00">status_code foo() {
              &nbsp; {
              &nbsp; &nbsp; status_code c = bar();
              &nbsp; &nbsp; if (c != SUCCESS) {
              &nbsp; &nbsp; &nbsp; return c;
              &nbsp; &nbsp; }
              &nbsp; }
              &nbsp; // ...
              }</div></td>
          <td><div class="code" style="color: #0A0">status_code foo() {
              &nbsp; if (status_code c = bar(); c != SUCCESS) {
              &nbsp; &nbsp; return c;
              &nbsp; }
              &nbsp; // ...
              }</div></td>
        </tr>

        <tr>
          <td><div class="code" style="color: #A00">void safe_init() {
              &nbsp; {
              &nbsp; &nbsp; std::lock_guard&lt;std::mutex&gt; lk(mx_);
              &nbsp; &nbsp; if (v.empty())
              &nbsp; &nbsp; &nbsp; v.push_back(kInitialValue);
              &nbsp; &nbsp; }
              &nbsp; }
              &nbsp; // ...
              }</div></td>
          <td><div class="code" style="color: #0A0">void safe_init() {
              &nbsp; if (std::lock_guard&lt;std::mutex&gt; lk(mx_); v.empty()) {
              &nbsp; &nbsp; v.push_back(kInitialValue);
              &nbsp; }
              &nbsp; // ...
              }</div>
            <p>(Consider having to move this code around.)</p></td>
        </tr>
        <tr>
          <td><div class="code" style="color: #A00">{
            &nbsp; Foo gadget(args);
            &nbsp; switch (auto s = gadget.status()) {
            &nbsp; &nbsp; case OK: gadget.zip(); break;
            &nbsp; &nbsp; case Bad: throw BadFoo(s.message());
            &nbsp; }
            }</div></td>
          <td><div class="code" style="color: #0A0">switch (Foo gadget(args); auto s = gadget.status()) {
            &nbsp; case OK: gadget.zip(); break;
            &nbsp; case Bad: throw BadFoo(s.message());
            }</div></td>
        </tr>
      </tbody>
    </table>

    <h2 id="proposal">Proposal</h2>

    <p>There are three statements in C++, <code>if</code>, <code>for</code> and <code>while</code>,
      which are all variations on a theme. We propose to make the picture more complete by adding
      a new form of <code>if</code> statement.
    </p>

    <table>
      <thead>
        <tr><th>Statement</th><th>Equivalent to<sup>*</sup></th><th>Iterations</th></tr>
      </thead>

      <tbody>
        <tr>
          <td><code>while(cond) E;</code></td>
          <td><code>{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(cond) { E; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } }</code></td>
          <td>Repeatedly while <code>cond</code> holds</td>
        </tr>

        <tr>
          <td><code>for (init; cond; inc) E;</code></td>
          <td><code>{ init; while(cond) { E; inc; &nbsp; } }</code></td>
          <td>Repeatedly while <code>cond</code> holds</td>
        </tr>

        <tr>
          <td><code>if (cond) E;</code></td>
          <td><code>{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(cond) { E; break; } }</code></td>
          <td>Once while <code>cond</code> holds</td>
        </tr>

        <tr>
          <td><code>if (cond) E; else F;</code></td>
          <td>(more complex)<sup>&dagger;</sup></td>
          <td>Once</td>
        </tr>

        <tr class="new">
          <td class="new"><code>if (init; cond) E;</code></td>
          <td><code>{ init; while(cond) { E; break; } }</code></td>
          <td>Once while <code>cond</code> holds</td>
        </tr>

        <tr class="new">
          <td class="new"><code>if (init; cond) E; else F;</code></td>
          <td>(more complex)<sup>&dagger;</sup></td>
          <td>Once</td>
        </tr>
      </tbody>
    </table>

    <div style="margin: -2em 0 2em 0;"><strong>Notes:</strong>
      <div style="font-size: smaller; margin: 0 2em;">
        *) The &ldquo;equivalence&rdquo; ignores the fact that <code>break</code> and <code>continue</code> have different semantics in loops.<br>
        &dagger;) The fact that there is no immediate expression of <code>else</code> blocks in terms of <code>while</code> is due to the
        absence of a fundamental <code>while ... else</code> construction from the language, which would in some sense be a &ldquo;universal control structure&rdquo;.
      </div>
    </div>

    <p>The <code>switch</code> statement too uses similar grammar, <code>switch (cond)</code>,
      and we also propose to extend this statement to allow the new form <code>switch (init; cond)</code>.
      This extension was not part of the previous revision of this proposal, but EWG suggested in Oulu
      that we may as well offer the same set of syntactic forms for all control structures consistently.</p>

    <h2 id="motivation">Motivation</h2>

    <p>The new form of the <code>if</code> statement has many uses. Currently, the initializer is
      either declared before the statement and leaked into the ambient scope, or an explicit scope
      is used. With the new form, such code can be written more compactly, and the improved scope
      control makes some erstwhile error-prone constructions a bit more robust:
    </p>

    <div class="code"><!--
    -->std::map&lt;int, std::string&gt; m;
      std::mutex mx;
      extern bool shared_flag;  // guarded by mx

      int demo()
      {
      &nbsp; if (auto it = m.find(10); it != m.end()) { return it-&gt;size(); }

      &nbsp; if (char buf[10]; std::fgets(buf, 10, stdin)) { m[0] += buf; }

      &nbsp; if (std::lock_guard&lt;std::mutex&gt; lock(mx); shared_flag) { unsafe_ping(); shared_flag = false; }

      &nbsp; if (int s; int count = ReadBytesWithSignal(&amp;s)) { publish(count); raise(s); }

      &nbsp; if (auto keywords = {"if", "for", "while"};
      &nbsp; &nbsp; &nbsp; std::any_of(keywords.begin(), keywords.end(), [&amp;s](const char* kw) { return s == kw; })) {
      &nbsp; &nbsp; ERROR("Token must not be a keyword");
      &nbsp; }
      }
    </div>

    <p>A certain &ldquo;monadic&rdquo; style of bubbling up non-success status values also
      becomes more compact:</p>
    <div class="code"><!-- -->status_code bar();

      status_code foo()
      {
      &nbsp; int n = get_value();
      &nbsp; if (status_code c = bar(n); c != status_code::SUCCESS) { return c; }
      &nbsp; if (status_code c = do_more_stuff(); c != status_code::SUCCESS) { return c; }
      &nbsp; return status_code::SUCCESS;
      }
    </div>

    <h2 id="alternatives">Alternatives</h2>

    <h3>No extension</h3>
    <p>There is always the alternative of using an equivalent construction, namely <code>{ init;
      if (cond) E; }</code>. However, this construction is more verbose, and users
      often use a &ldquo;lazy approximation&rdquo; that omits the extra scope. such as:</p>
    <div class="code"><!--
    -->auto it = m.find(10);
      if (it != m.end()) { return it-&gt;size(); }

      // "it" is leaked into the ambient scope.
    </div>
    <p>This is often just as good, but in certain cases where the lifetime of the object
      created in the initializer is important, such as when locking a mutex, forgetting the
      extra scope may easily have hard-to-diagnose adverse effects. Moreover, the explicit
      additional scope is brittle and may get lost during refactoring.</p>
    <p>A common naming convention is that the length of a name of should correspond to the
      size of its scope; offering a convenient way to declare names in tight scopes makes
      it easier to follow such a principle without either introducing unwanted nesting
      levels or using artificially long names.</p>

    <h3>Library solution</h3>
    <p>It is possible to write a library gadget that could contain both initialized
      values and the result of a boolean expression, but all such attempts have turned up
      something very unsightly.</p>

    <h3>Other language extensions</h3>
    <p>An alternative language extension could be of the form <code>with (init) if
      (cond) E;</code>. Constructions like this exist in other languages. While certainly
      conceivable, such an extension is more expensive (new keyword, more to teach) and
      misses out on the opportunity to make an existing facility more consistent.</p>

    <h2 id="discussion">Discussion</h2>

    <p>It is often said that C++ is already complex enough, and any additional complexity needs
      to be carefully justified. We believe that the proposed extension is natural and unsurprising,
      and thus adds minimal complexity, and perhaps even removes some of the existing differences
      among the various control flow statements. There is nothing about the local initialization
      that is specific to loop statements, so having it only on the loop and not on the selection
      statement seems arbitrary. Had the initializer form of the <code>if</code> statement been in
      the language from the start, it would not have seemed out of place. (At best one might have
      wondered why <code>for</code> is not also spelled <code>while</code>, or vice versa.)</p>

    <p>For the second point, we would like to consider the advantages of the new form of the
      <code>if</code> statement. Names, lifetimes and scopes are fundamental concepts of C++,
      and putting the right names into the right scopes is instrumental to understandability
      and maintainability. The proposed extension is mere syntactic sugar, but it is a
      convenient tool, readily understood by the reader, that allows the user to keep the
      scope of auxiliary variables minimal. Current code either requires additional braces
      to keep scopes minimal, which are visually noisy (taking up valuable indentation levels!)
      and burdensome to refactor (think of keeping all the lines together), or simply omits
      the braces, leaking local variables into larger scopes.</p>

    <p>Real, existing code bases contain macros that wrap up common idioms (like map lookup
      and error status propagation), because users find macros the smaller of the two evils
      compared to leaking lots of local variables or using excessive braces. The proposal
      removes a common use case for macros.</p>

    <p>Note also that the Go language allows initial statements for both <code>if</code> and
      <code>switch</code> statements.</p>

    <h2 id="impact">Impact on the Standard</h2>

    <p>This is a core language extension. The newly proposed syntax is ill-formed in the
      current working draft.</p>

    <h2 id="ack">Acknowledgements</h2>

    <p>Many thanks to Jens Maurer for invaluable help with the wording.</p>

    <h2 id="wording">Proposed wording</h2>

    <p>As part of the wording change, we will rename the grammar production
      <em>for-init-statement</em> to just <em>init-statement</em>. In section
      3.3.3 [basic.block.scope], change paragraph 4 as follows.</p>

    <div class="modify">
      <p>Names declared in the <del><em>for-init-statement</em></del><ins><em>init-statement</em></ins>,
        the <em>for-range-declaration</em>, and the <em>condition</em> of <code>if</code>, <code>while</code>,
        <code>for</code>, and <code>switch</code> statements [&hellip;]</p>
    </div>

    <p>Append the following grammar to clause 6 [stmt.stmt].</p>

    <div class="modify">
      &nbsp;&nbsp;<em>declaration-statement</em><br>
      &nbsp;&nbsp;<em>attribute-specifier-seq<sub>opt</sub></em> <em>try-block</em><br>
      <br>
      <ins><em>init-statement</em>:</ins><br>
      &nbsp;&nbsp;<ins><em>expression-statement</em></ins><br>
      &nbsp;&nbsp;<ins><em>simple-declaration</em></ins>
    </div>

    <p>In section 6.4 [stmt.select], change the grammar in paragraph 1 as follows.</p>

    <div class="modify">
      <em>selection statement</em>:<br>
      &nbsp; &nbsp; <code>if (</code> <ins><em>init-statement</em><sub><em>opt</em></sub></ins> <em>condition</em> <code>)</code> <em>statement</em><br>
      &nbsp; &nbsp; <code>if (</code> <ins><em>init-statement</em><sub><em>opt</em></sub></ins> <em>condition</em> <code>)</code> <em>statement</em> <code>else</code> <em>statement</em><br>
      &nbsp; &nbsp; <code>switch (</code> <ins><em>init-statement</em><sub><em>opt</em></sub></ins> <em>condition</em> <code>)</code> <em>statement</em>
    </div>

    <p>Change the first sentence as follows.</p>

    <div class="modify">
      <p>See 8.3 for the optional <em>attribute-specifier-seq</em> in a condition.
        <ins>[<em>Note</em>: An <em>init-statement</em> ends with a semicolon. &ndash; <em>end note</em>]</ins>
        In Clause 6, the term [&hellip;]</p>
    </div>

    <p>Insert a new paragraph at the end of subsection 6.4.1 [stmt.if].</p>

    <div class="insert">
      <p><ins>An <code>if</code> statement of the form</ins></p>
      <div class="code"><ins>if ( <em>init-statement condition</em> ) <em>statement</em></ins></div>
      <p><ins>is equivalent to</ins></p>
      <div class="code"><ins>{</ins>
        &nbsp; <ins><em>init-statement</em></ins>
        &nbsp; <ins>if ( <em>condition</em> ) <em>statement</em></ins>
        <ins>}</ins></div>
      <p><ins>and an <code>if</code> statement of the form</ins></p>
      <div class="code"><ins>if ( <em>init-statement condition</em> ) <em>statement</em> else <em>statement</em></ins></div>
      <p><ins>is equivalent to</ins></p>
      <div class="code"><ins>{</ins>
        &nbsp; <ins><em>init-statement</em></ins>
        &nbsp; <ins>if ( <em>condition</em> ) <em>statement</em> else <em>statement</em></ins>
        <ins>}</ins></div>
      <p><ins>except that names declared in the <em>init-statement</em> are in the same
        declarative region as those declared in the <em>condition</em>.</ins></p>
    </div>

    <p>Insert a new paragraph at the end of subsection 6.4.2 [stmt.switch].</p>

    <div class="insert">
      <p><ins>A <code>switch</code> statement of the form</ins></p>
      <div class="code"><ins>switch ( <em>init-statement condition</em> ) <em>statement</em></ins></div>
      <p><ins>is equivalent to</ins></p>
      <div class="code"><ins>{</ins>
        &nbsp; <ins><em>init-statement</em></ins>
        &nbsp; <ins>switch ( <em>condition</em> ) <em>statement</em></ins>
        <ins>}</ins></div>
      <p><ins>except that names declared in the <em>init-statement</em> are in the same
        declarative region as those declared in the <em>condition</em>.</ins></p>
    </div>

    <p>In section 6.5 [stmt.iter], modify paragraph 1 as follows.</p>

    <div class="modify">
      <code>for (</code> <del><em>for-init-statement</em></del><ins><em>init-statement</em></ins> <em>condition</em><sub><em>opt</em></sub> <code>;</code> <em>expression</em><sub><em>opt</em></sub> <code>)</code> <em>statement</em><br>
      <code>for (</code> <em>for-range-declaration</em> <code>:</code> <em>for-range-initializer</em> <code>)</code> <em>statement</em><br>
      <br>
      <del><em>for-init-statement</em>:</del><br>
      &nbsp;&nbsp;<del><em>expression-statement</em></del><br>
      &nbsp;&nbsp;<del><em>simple-declaration</em></del><br>
      <br>
      <em>for-range-declaration</em>:<br>
      &nbsp;&nbsp;<em>attribute-specifier-seq<sub>opt</sub></em> <em>decl-specifier-seq</em> <em>declarator</em><br>
      <br>
      <em>for-range-initializer</em>:<br>
      &nbsp;&nbsp;<em>expr-or-braced-init-list</em><br>
      <p>See 8.3 for the optional <em>attribute-specifier-seq</em> in a <em>for-range-declaration</em>.
        [<em>Note</em>: <del>A <em>for-init-statement</em></del><ins>An <em>init-statement</em></ins> ends
        with a semicolon. &ndash; <em>end note</em>]</p>
    </div>

    <p>In section 6.5.3 [stmt.for], change paragraph 1 as follows.</p>

    <div class="modify">
      <p>The <code>for</code> statement</p>
      <div class="code">for ( <del><em>for-init-statement</em></del><ins><em>init-statement</em></ins> <em>condition</em><sub><em>opt</em></sub> ; <em>expression</em><sub><em>opt</em></sub> ) <em>statement</em></div>
      <p>is equivalent to</p>
      <div class="code">{
        &nbsp;&nbsp;<del><em>for-init-statement</em></del><ins><em>init-statement</em></ins>
        &nbsp;&nbsp;while ( <em>condition</em> ) {
        &nbsp;&nbsp;&nbsp;&nbsp;<em>statement</em>
        &nbsp;&nbsp;&nbsp;&nbsp;<em>expression</em> ;
        &nbsp;&nbsp;}
        }
      </div>
      <p>except that names declared in the <del><em>for-init-statement</em></del><ins><em>init-statement</em></ins> are in the same [&hellip;]</p>
    </div>

    <p>Change paragraph 3 as follows.</p>

    <div class="modify">
      If the <del><em>for-init-statement</em></del><ins><em>init-statement</em></ins> is a declaration [&hellip;]
    </div>

    <p>In section 7.1.6.4 [dcl.spec.auto], change paragraph 4 as follows.</p>

    <div class="modify">
      [&hellip;] in namespace scope (3.3.6), and in <del>a <em>for-init-statement</em>
      (6.5.3)</del><ins>an <em>init-statement</em> (Clause 6)</ins>. [&hellip;]
    </div>

    <h2 id="constexpr">If constexpr</h2>

    <p>In Oulu, EWG also requested that this proposal incorporate the addition of <code>if constexpr</code>,
      which has been approved by EWG and CWG in
      <a href="http://wiki.edg.com/pub/Wg21oulu/StrawPolls/p0292r2.html">P0292r2</a>. That proposal
      and the present one are largely orthogonal, and the facilities of <code>if constexpr</code> work
      just as well with the extended <code>if</code> statement from this proposal. For example, the new
      grammar will be (with changes appertaining to P0292r2 shown as <span class="box">boxed</span>):</p>

    <div class="modify">
      <em>selection statement</em>:<br>
      &nbsp; &nbsp; <code>if</code> <span class="box"><ins><code>constexpr</code><sub><em>opt</em></sub></ins></span> <code>(</code> <ins><em>init-statement</em><sub><em>opt</em></sub></ins> <em>condition</em> <code>)</code> <em>statement</em><br>
      &nbsp; &nbsp; <code>if</code> <span class="box"><ins><code>constexpr</code><sub><em>opt</em></sub></ins></span> <code>(</code> <ins><em>init-statement</em><sub><em>opt</em></sub></ins> <em>condition</em> <code>)</code> <em>statement</em> <code>else</code> <em>statement</em><br>
      &nbsp; &nbsp; <code>switch (</code> <ins><em>init-statement</em><sub><em>opt</em></sub></ins> <em>condition</em> <code>)</code> <em>statement</em>
    </div>

    <p><em>Drafting note.</em> Care should be taken to apply the new <code>constexpr</code><sub><em>opt</em></sub>
      from P0292r2 to the grammar excerpts in the new paragraph in subsection 6.4.1.</p>

    <p>The first sentence of the new wording from P0292r2 needs to be modified to make the reference to the
      constexpr form of the if statement clearer:</p>

    <div class="modify">
      <span class="box">If the <del>parenthesized <em>condition</em> is prefixed with <code>constexpr</code></del>
        <ins><code>if</code> statement is of the form <code>if constexpr</code></ins>,</span>
    </div>

  </body>
</html>
