<html>
<style>
ins {background-color:#A0FFA0}
del {background-color:#FFA0A0}
strong { color: #2020ff }
#hidedel:checked ~ * del, #hidedel:checked ~ * del * { display:none; visibility:hidden }
</style>
<title>Drafting for CA096: Declaration matching for non-dependent requires-clauses</title>
<body>
<h1>Drafting for CA096: Declaration matching for non-dependent requires-clauses</h1>

<table>
  <tr align="left"><th>Document Number:</th> <th>P1980R0</th></tr>
  <tr align="left"><th>Date:</th> <th>2019-11-08</th></tr>
  <tr align="left"><th>Audience:</th> <th>Core Working Group</th></tr>
  <tr align="left"><th>Author:</th> <th>Jason Merrill</th></tr>
</table>

<BR><HR>

<h4>National Body Comment CA096: Declaration matching for non-dependent requires-clauses</h4>

  Declaration matching ([over.dcl]) is based upon whether trailing
  requires-clauses are equivalent; however, equivalent, with respect to
  expressions ([temp.over.link]), is defined only for expressions involving
  template parameters.

<p/>
Proposed change:<br/>

  Extend the definitions of equivalent and functionally equivalent to cover
  expressions subject to normalization in general (not just those involving
  template parameters).

<br/> Further, make the determination of expression equivalence treat concept
definitions as opaque by adding a condition that an expression that may be
subject to constraint normalization is functionally equivalent only if each
qualified-concept-name that may be expanded by normalization would be
considered to name the same type if, instead of a concept, a class template was
named.

<BR><HR>

<a name="drafting" />

<h3>Drafting note</h3>

This drafting clarifies the status of non-dependent requires-clauses by
pointing out that they are unevaluated operands, and therefore contained
concept-ids are not evaluated unless they appear in a manifestly
constant-evaluated expression.

<p/>Importantly, a constraint-expression is no longer manifestly
constant-evaluated, only the result of atomic constraint expression
substitution during satisfaction.

<p/>This also resolves US095.

<h3>Proposed Resolution</h3>

Remove 7.5.4 [expr.prim.id] (to move it to clause 13):

<blockquote>
  <del>An id-expression that denotes the specialization of a concept (13.7.8)
  results in a prvalue of type bool.  The expression is true if the concept's
  normalized constraint-expression (13.5.2) is satisfied (13.5.1) by the
    specified template arguments and false otherwise. [Example:</del>
<pre>
  <del>template&lt;typename T> concept C = true;</del>
  <del>static_assert(C&lt;int>);      // OK</del>
</pre>
<del>-- end example] [Note: A concept's constraints are also considered when using a template name (13.3) and
during overload resolution (Clause 12), and they are compared during the partial ordering of constraints
  (13.5.4). -- end note]</del>
</blockquote>

Change 7.7 [expr.const]/12-13:

<blockquote>
  An expression or conversion is in an immediate function context if it is
  potentially evaluated and its innermost non-block scope is a function
  parameter scope of an immediate function. An expression or conversion is an
  immediate invocation if it is an explicit or implicit invocation of an
  immediate function and is not in an immediate function context. An immediate
  invocation shall be a constant expression. <del>[Note: An immediate invocation is
    evaluated even in an unevaluated operand. -- end note]</del>

<p/>
 
  An expression or conversion e is manifestly constant-evaluated if it is:
<ul><li>...</li>
  <li><del>a constraint-expression (13.5.2) including one formed from the
      constraint-logical-or-expression of a requires-clause</del> <ins>the
      result of substitution into an atomic constraint expression to determine
      whether it is satisfied (13.5.1.2)</ins> , or</li>
  <li>...</li>
</ul>
<ins>[Note: A manifestly constant-evaluated expression is evaluated even in an
  unevaluated operand. -- end note]</ins>
  <p/>
</blockquote>

Change 12.3 [over.dcl]:

<blockquote>
  Two function declarations of the same name refer to the same function if they
  are in the same scope and have equivalent parameter declarations (12.2) and
  equivalent <ins>(13.7.6.1)</ins>
  trailing requires-clauses, if any (9.3).
  <ins>[Note: since a constraint-expression is an unevaluated operand,
  equivalence compares the expressions without evaluating them.
    [Example:</ins>
<pre>
  <ins>template&lt;int I> concept C = true;</ins>
  <ins>template&lt;typename T> struct A {</ins>
    <ins>void f() requires C&lt;42>; // #1</ins>
    <ins>void f() requires true; // OK, different functions</ins>
  <ins>};</ins>
</pre>
<ins>--end example] --end note]</ins> <p/>A function member
  of a derived class is not in the same scope as a function member of the same
  name in a base class.
</blockquote>

No change to 13.1 [temp.pre]/10:

<blockquote>
  A template-declaration is written in terms of its template parameters. The
  optional requires-clause following a template-parameter-list allows the
  specification of constraints (13.5.2) on template arguments (13.4). The
  requires-clause introduces the constraint-expression that results from
  interpreting the constraint-logical-or-expression as a
  constraint-expression. The constraint-logical-or-expression of a
  requires-clause is an unevaluated operand (Clause 7). [Note: The expression
  in a requires-clause uses a restricted grammar to avoid ambiguities.
  Parentheses can be used to specify arbitrary expressions in a
  requires-clause. [Example:
<pre>
  template&lt;int N> requires N == sizeof new unsigned short
  int f();  // error: parentheses required around == expression
</pre>
-- end example] -- end note]
</blockquote>

Add to the end of 13.3 [temp.names]:

<blockquote>
  <ins>A <i>concept-id</i> is a simple-template-id where the template-name is a
  concept-name.  A concept-id is a prvalue of type bool, and does not name a
  template specialization.  A concept-id evaluates to true if the concept's
  normalized constraint-expression (13.5.2) is satisfied (13.5.1) by the
  specified template arguments and false otherwise. [Note: Since a
  constraint-expression is an unevaluated operand, a concept-id appearing in a
  constraint-expression is not evaluated except as necessary to determine
  whether the normalized constraints are satisfied. --end note] [Example:</ins>
<pre>
  <ins>template&lt;typename T> concept C = true;</ins>
  <ins>static_assert(C&lt;int>);      // OK</ins>
</pre>
<ins> -- end example] </ins>
</blockquote>

Change 13.5.3 [temp.constr.normal]/1.4:

<blockquote>
<ul>
  <li>
    The normal form of
    <del>an id-expression of the form</del> <ins>a concept-id</ins> C&lt;A 1 , A 2
     , ..., A n ><del>, where C names a concept,</del> is the normal form of
     the constraint-expression of C, after substituting A 1 , A 2 , ..., A n
     for C's respective template parameters in the parameter mappings in each
    atomic constraint.
  </li>
</ul>
</blockquote>

Change 13.7.6.1 [temp.over.link]/5:

<blockquote>
  Two expressions involving template parameters are considered equivalent if
  two function definitions containing the expressions would satisfy the
  one-definition rule (6.3), except that the tokens used to name the template
  parameters may differ as long as a token used to name a template parameter in
  one expression is replaced by another token that names the same template
  parameter in the other expression.

  <ins>Two unevaluated operands that do not involve template parameters are
  considered equivalent if two function definitions containing the expressions
  would satisfy the one-definition rule, except that the tokens used to name
  types and declarations may differ as long as they name the same entities, and
  the tokens used to form concept-ids may differ as long as the two
  template-ids would be considered to name the same type if, instead of a
  concept, a class template were named. [Note: For instance, A&lt;42> and
  A&lt;40+2> name the same type. --end note ]</ins>

  Two lambda-expressions are never considered equivalent. [Note: The intent is
  to avoid lambda-expressions appearing in the signature of a function template
  with external linkage. --end note] For determining whether two dependent
  names (13.8.2) are equivalent, only the name itself is considered, not the
  result of name lookup in the context of the template.  If multiple
  declarations of the same function template differ in the result of this name
  lookup, the result for the first declaration is used. [Example: <p/>....<p/>
  --end example]

  Two <ins>potentially-evaluated</ins> expressions
  involving template parameters that are not equivalent are functionally
  equivalent if, for any given set of template arguments, the evaluation of the
  expression results in the same value.

  <ins>Two unevaluated operands that are not equivalent are functionally
  equivalent if, for any given set of template arguments, the expressions
  perform the same operations in the same order with the same entities.
  [Note: For instance, one could have redundant parentheses.  --end note]</ins>
</blockquote>

Change 13.7.8 [temp.concept]/5:

<blockquote>
  A concept is not instantiated (13.9). [Note: <del>An id-expression that
    denotes a concept specialization</del> <ins>A concept-id (13.3)</ins> is
    evaluated as an expression <del>(7.5.4)</del> . A concept cannot be
    explicitly instantiated (13.9.2), explicitly specialized (13.9.3), or
  partially specialized. -- end note]
<p/>
<ins>The constraint-expression of a concept-definition is an unevaluated operand.</ins>
</blockquote>

</body>
</html>
