<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html>
  <head>
    <meta content="text/html;charset=UTF-8" http-equiv="Content-Type">
    <title>Wording for &ldquo;functionality gaps in constraints&rdquo;</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: 0 auto 3em auto; }
      thead th { border-bottom: 2px solid black; }
      tr.midsep td { border-top: 2px solid black; }
      th, td { text-align: left; vertical-align: top; padding: 1ex 1ex 1ex 1em; }
      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; }

      table.features { width: 100%; }
      .features tr a { font-family: "DejaVu Sans", sans-serif; text-decoration: none; }
      .features tbody tr { border-bottom: thin solid black; }
      .features tr td:first-child { width: 3em; }
      .features tr td:first-child + td { width: 20%; }
      .features tbody tr:hover { background-color: #F9F9FF; }

      .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; }

      h1 { counter-reset: item; }
      h2 { counter-increment: item; }
      h2:before { content: counter(item, upper-alpha) "\00A0\00A0\00A0"; }
    </style>
  </head>
  <body>
    <div class="docinfo">
      <p>ISO/IEC JTC1 SC22 WG21 P0857R0</p>
      <p>Date: 2017-11-10</p>
      <p>To: CWG</p>
      <address>
        Thomas K&ouml;ppe &lt;<a href="mailto:tkoeppe@google.com">tkoeppe@google.com</a>&gt;<br>
      </address>
    </div>

    <h1>Wording for &ldquo;functionality gaps in constraints&rdquo;</h1>

    <p>This paper contains formal wording for the two extensions proposed in
      <a href="https://wg21.link/p0766r1">P0766r1: Fixing small-ish functionality
      gaps in constraints</a> that concern <em>requires-clause</em>s.</p>

    <h2>Proposed wording for constrained lambdas</h2>

    <p>Modify the grammar in [expr.prim.lambda, 8.1.5] as follows.</p>

    <div class="modify"><em>lambda-expression</em>:<br>
      &nbsp; &nbsp; <ins><em>lambda-introducer</em> <em>compound-statement</em></ins><br>
      &nbsp; &nbsp; <em>lambda-introducer</em> <em>lambda-declarator</em><sub><del>opt</del></sub> <ins><em>requires-clause</em><sub>opt</sub></ins> <em>compound-statement</em><br>
      &nbsp; &nbsp; <ins><em>lambda-introducer</em> <code>&lt;</code> <em>template-parameter-list</em>
      <code>&gt;</code> <em>requires-clause</em><sub>opt</sub> <em>compound-statement</em></ins><br>
      &nbsp; &nbsp; <em>lambda-introducer</em> <code>&lt;</code> <em>template-parameter-list</em>
      <code>&gt;</code> <ins><em>requires-clause</em><sub>opt</sub></ins> <em>lambda-declarator</em><sub><del>opt</del></sub>
      <ins><em>requires-clause</em><sub>opt</sub></ins> <em>compound-statement</em>
    </div>

    <p>Modify [expr.prim.lambda, 8.1.5] paragraph 3 as follows.</p>
    <div class="modify">In the <em>decl-specifier-seq</em> of the <em>lambda-declarator</em>,
      each <em>decl-specifier</em> shall either be <code>mutable</code> or <code>constexpr</code>.
      <ins>[<em>Note</em>: The trailing <em>requires-clause</em> is described in Clause [dcl.decl, 11]. &ndash; <em>end note</em>]</ins></div>

    <p>Modify [expr.prim.lambda, 8.1.5.1] paragraph 3 as follows.</p>
    <div class="modify">
      The closure type for a non-generic <em>lambda-expression</em> has a public inline function call operator (16.5.4)
      whose parameters and return type are described by the <em>lambda-expression</em>&rsquo;s <em>parameter-declaration-clause</em>
      and <em>trailing-return-type</em> respectively. For a generic lambda, the closure type has a public inline function
      call operator member template (17.6.2) whose <em>template-parameter-list</em> consists of the specified <em>template-parameter-list</em>,
      if any, to which is appended one invented type <em>template-parameter</em> for each occurrence of
      <code>auto</code> in the lambda&rsquo;s <em>parameter-declaration-clause</em>, in order of appearance.
      The invented type <em>template-parameter</em> is a parameter pack if the corresponding <em>parameter-declaration</em> declares a function parameter
      pack (11.3.5).
      The return type and function parameters of the function call operator template are derived from
      the <em>lambda-expression</em>&rsquo;s <em>trailing-return-type</em> and <em>parameter-declaration-clause</em>
      by replacing each occurrence of auto in the decl-specifiers of the parameter-declaration-clause with the name of the corresponding invented
      template-parameter.
      <ins>The <em>requires-clause</em> of the function call operator template is the <em>requires-clause</em>
        immediately following <code>&lt;</code>&nbsp;<em>template-parameter-list</em>&nbsp;<code>&gt;</code>, if any. The trailing <em>requires-clause</em> of the
        function call operator or operator template is the <em>requires-clause</em> following the <em>lambda-declarator</em>, if any.</ins>
      [<em>Example</em>: [&hellip;]
    </div>

    <p>Modify [expr.prim.lambda, 8.1.5.1] paragraph 6 as follows.</p>
    <div class="modify">
      The closure type for a non-generic <em>lambda-expression</em> with no <em>lambda-capture</em>
      <ins>whose constraints (if any) are satisfied</ins>
      has a conversion function to pointer to function with C++ language linkage (10.5) having the
      same parameter and return types as the closure type&rsquo;s function call operator.
      The conversion is to &ldquo;pointer to <code>noexcept</code> function&rdquo; if the function
      call operator has a non-throwing exception specification.
      The value returned by this conversion function is the address of a function <code>F</code> that,
      when invoked, has the same effect as [&hellip;]
    </div>

    <p>Insert a new paragraph between paragraphs 5 and 6 of [expr.prim.lambda.closure, 8.1.5.1].</p>
    <div class="insert">
      <p>[&hellip;] &ndash; <em>end example</em>]</p>

      <p><ins>The function call operator or operator template may be constrained ([temp.constr.decl, 17.4.2])
        by a <em>constrained-parameter</em> ([temp.param, 17.1]), a <em>requires-clause</em> (Clause [temp, 17]),
        or a trailing <em>requires-clause</em> (Clause [dcl.decl, 11]). [<em>Example</em>:</ins></p>
      <div class="code"><ins>template &lt;typename T&gt; concept C1 = /* ... */;
          template &lt;std::size_t N&gt; concept C2 = /* ... */;
          template &lt;typename A, typename B&gt; concept C3 = /* ... */;

          auto f = []&lt;typename T1, C1 T2&gt; requires C2&lt;sizeof(T1) + sizeof(T2)&gt;</ins>
          &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<ins>(T1 a1, T1 b1, T2 a2, auto a3, auto a4) requires C3&lt;decltype(a4), T2&gt; {</ins>
          &nbsp; <ins>// T2 is a constrained parameter,</ins>
          &nbsp; <ins>// T1 and T2 are constrained by a <i>requires-clause</i>, and</ins>
          &nbsp; <ins>// T2 and the type of a4 are constrained by a trailing <i>requires-clause</i>.
          };
      </ins></div>
      <p><ins>&ndash; <em>end example</em>]</ins></p>

      <p>The closure type for a non-generic <em>lambda-expression</em> [&hellip;]</p>
    </div>

    <h2>Proposed wording for constrained template <em>template-parameter</em>s</h2>

    <p>Modify the grammar in [temp.param, 17.1] as follows.</p>
    <div class="modify"><em>template-parameter</em>:<br>
      &nbsp; &nbsp; [&hellip;]<br><br>
      <em>type-parameter</em>:<br>
      &nbsp; &nbsp; <em>type-parameter-key</em> <code>...</code><sub>opt</sub> <em>identifier</em><sub>opt</sub><br>
      &nbsp; &nbsp; <em>type-parameter-key</em> <em>identifier</em><sub>opt</sub> <code>=</code> <em>type-id</em><br>
      &nbsp; &nbsp; <del><code>template &lt;</code> <em>template-parameter-list</em> <code>&gt;</code></del><ins><em>template-head</em></ins>
      <em>type-parameter-key</em> <code>...</code><sub>opt</sub> <em>identifier</em><sub>opt</sub><br>
      &nbsp; &nbsp; <del><code>template &lt;</code> <em>template-parameter-list</em> <code>&gt;</code></del><ins><em>template-head</em></ins>
      <em>type-parameter-key</em> <em>identifier</em><sub>opt</sub> = <em>id-expression</em><br><br>
      <em>type-parameter-key</em>:<br>
      &nbsp; &nbsp; [&hellip;]</div>

    <p>Modify [temp.arg.template, 17.3.3], paragraph 3 as follows.</p>
    <div class="modify">
      A <em>template-argument</em> matches a template <em>template-parameter</em> <code>P</code> when <code>P</code>
      is at least as specialized as the <em>template-argument</em> <code>A</code>. If <code>P</code> contains a parameter
      pack, then <code>A</code> also matches <code>P</code> if each of <code>A</code>&rsquo;s template parameters
      matches the corresponding template parameter in the <em><del>template-parameter-list</del><ins>template-head</ins></em> of <code>P</code>. Two template parameters
      match if they are of the same kind (type, non-type, template), for non-type <em>template-parameters</em>, their types are
      equivalent (17.6.6.1), and for template <em>template-parameters</em>, each of their corresponding <em>template-parameters</em>
      matches, recursively. When <code>P</code>&rsquo;s <em><del>template-parameter-list</del><ins>template-head</ins></em> contains a template parameter pack (17.6.3), the
      template parameter pack will match zero or more template parameters or template parameter packs in the
      <em><del>template-parameter-list</del><ins>template-head</ins></em> of <code>A</code> with the same type and form as the template parameter pack in <code>P</code> (ignoring
      whether those template parameters are template parameter packs).
      [<em>Example</em>: [&hellip;]</div>

    <p>Modify [temp.arg.template, 17.3.3], paragraph 4 as follows.</p>
    <div class="modify"><p>A template <em>template-parameter</em> <code>P</code> is at least as specialized as a template <em>template-argument</em> <code>A</code> if, given
      the following rewrite to two function templates, the function template corresponding to <code>P</code>
      is at least as
      specialized as the function template corresponding to <code>A</code> according to the partial ordering rules for function
      templates (17.6.6.2). Given an invented class template <code>X</code> with the <del>template parameter list</del><ins><em>template-head</em></ins> of <code>A</code> (including
      default arguments<ins> and <em>requires-clause</em>, if any</ins>):</p>
      <ul>
        <li>
          Each of the two function templates has the same template parameters<ins> and <em>requires-clause</em> (if any)</ins>,
          respectively, as <code>P</code> or <code>A</code>.
        </li>
        <li>
          Each function template has a single function parameter whose type is a specialization
          of <code>X</code> with template
          arguments corresponding to the template parameters from the respective function template where, for
          each template parameter <code>PP</code> in the <del>template parameter list</del><ins><em>template-head</em></ins>
          of the function template, a corresponding template argument <code>AA</code> is formed. If <code>PP</code>
          declares a parameter pack, then <code>AA</code> is the pack expansion
          <code>PP...</code> (17.6.3); otherwise, <code>AA</code> is the <em>id-expression</em> <code>PP</code>.
        </li>
      </ul>
      <p>If the rewrite produces an invalid type, then <code>P</code> is not at least as specialized as <code>A</code>.</p>
    </div>
  </body>
</html>
