<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>P0859R0: Core Issue 1581: When are constexpr member functions defined?</title>

<style type="text/css">
  ins, ins > * { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  del, del > * { text-decoration:line-through; background-color:#FFA0A0 }

  .new { /*color: blue;*/ }

blockquote {
  color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em;
}
blockquote.stdins {
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3;
  padding-left: 0.5em; padding-right: 0.5em;
}
blockquote.stddel {
  text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5em; padding-right: 0.5em;
}
</style>

</head>

<body>
Richard Smith<br>
2017-11-09

<h1>P0859R0: Core Issue 1581: When are constexpr member functions defined?</h1>

This paper provides wording for Core Issue 1581.

<p>
Change in basic.def.odr 6.2 paragraph 3,
and <b>move the indicated portion to a new paragraph prior to
paragraph 3</b>:
</p>

<blockquote>
[&hellip;]
A virtual member function is odr-used if it is not pure.
<ins>A function is odr-used if it is named by a potentially-evaluated expression.</ins>

<p>
<i>Begin text to be moved to new paragraph</i>

<p>
<ins>A function is <i>named by an expression</i> as follows:</ins>
<ul>
<li>
A function whose name appears
<ins>in an expression is named by that expression</ins>
<del>as a potentially-evaluated expression is odr-used</del>
if it is the unique lookup result or
the selected member of a set of overloaded functions
(6.4, 16.3, 16.4),
unless it is a pure virtual function and
either its name is not explicitly qualified or
the expression forms a pointer to member (8.3.1).
[ <i>Note</i>: This covers
<ins>taking the address of functions ([conv.func], [expr.unary.op]),</ins>
calls to named functions (8.2.2),
operator overloading (Clause 16),
user-defined conversions (15.3.2),
allocation functions for placement new-expressions (8.3.4),
as well as non-default initialization (11.6).
A constructor selected to copy or move an object of class type is
<ins>considered to be named by an expression</ins> <del>odr-used</del>
even if the call is actually elided by the implementation (15.8).
&mdash; <i>end note</i> ]
<li>
An allocation or deallocation function for a class is
<ins>named</ins> <del>odr-used</del>
by a new-expression
<del>appearing in a potentially-evaluated expression</del>
as specified in 8.3.4 and 15.5.
<li>
A deallocation function for a class is
<ins>named</ins> <del>odr-used</del>
by a delete expression
<del>appearing in a potentially-evaluated expression</del>
as specified in 8.3.5 and 15.5.
</ul>

<p>
<i>End text to be moved to new paragraph</i>

<p>
A non-placement allocation or deallocation function for a class
is odr-used
by the definition of a constructor of that class.
A non-placement deallocation function for a class is odr-used
by the definition of the destructor of that class,
or by being selected by the lookup at the point of definition
of a virtual destructor (15.4).
An assignment operator function in a class
is odr-used
by an implicitly-defined copy-assignment or move-assignment function
for another class as specified in 15.8.
A constructor for a class is odr-used as specified in 11.6.
A destructor for a class is odr-used if it is potentially invoked (15.4).
</blockquote>

<p>
Append a paragraph to expr.const 6.2:
</p>

<blockquote class="stdins">
An expression is <i>potentially constant evaluated</i> if it is:
<ul>
<li>a potentially-evaluated expression ([basic.def.odr]),
<li>a <i>constraint-expression</i>,
including one formed from the <i>constraint-logical-or-expression</i> of a <i>requires-clause</i>,
<li>a<span class="new">n immediate</span> subexpression of a <i>braced-init-list</i>[&nbsp;<i>Footnote</i>: Constant evaluation may be necessary to determine whether a narrowing conversion is performed ([dcl.init.list]). ],
<li>an expression of the form <tt>&</tt> <i>cast-expression</i> that occurs within a templated entity[&nbsp;<i>Footnote</i>: Constant evaluation may be necessary to determine whether such an expression is value-dependent ([temp.dep.constexpr]). ], or
<li>a subexpression of one of the above that is not a subexpression of a nested unevaluated operand.
</ul>
A function or variable is <i>needed for constant evaluation</i> if it is:
<ul>
<li>
a constexpr function that is named by an expression ([basic.def.odr])
that is potentially constant evaluated, or
<li>
a variable whose name appears as a potentially constant evaluated expression
that is either a constexpr variable or is of non-volatile const-qualified
integral type or of reference type.
</ul>
</blockquote>

<p>Change in special 15 paragraph 1:</p>

<blockquote>
[Note: The implementation will implicitly declare these member functions for
some class types when the program does not explicitly declare them.
The implementation will implicitly define them if they are odr-used (6.2)
<ins>or needed for constant evaluation ([expr.const])</ins>.
See 15.1, 15.4 and 15.8. &mdash; end note ]
[&hellip;]
</blockquote>

<p>Change in class.ctor 15.1 paragraph 7:</p>

<blockquote>
A default constructor that is defaulted and not defined as deleted is
implicitly defined when it is odr-used (6.2)
to create an object of its class type (4.5)<ins>,
when it is needed for constant evaluation ([expr.const]),</ins>
or when it is explicitly defaulted after its first declaration.
</blockquote>

<p>No change in class.dtor 15.4 paragraph 7:</p>

<blockquote>
A destructor that is defaulted and not defined as deleted is implicitly defined
when it is odr-used (6.2) or when it is
explicitly defaulted after its first declaration.
</blockquote>

<p>Change in class.copy.ctor 15.8.1 paragraph 12:</p>

<blockquote>
A copy/move constructor that is defaulted
and not defined as deleted
is implicitly defined <del>if</del> <ins>when</ins> it is odr-used (6.2)<ins>,
when it is needed for constant evaluation ([expr.const]),</ins>
</ins> or when it is explicitly defaulted
after its first declaration.
</blockquote>

<p>Change in class.copy.assign 15.8.2 paragraph 10:</p>

<blockquote>
A copy/move assignment operator for a class X that is defaulted
and not defined as deleted
is implicitly defined when it is odr-used (6.2)
(e.g., when it is selected by overload resolution
to assign to an object of its class type)<ins>,
when it is needed for constant evaluation ([expr.const]),</ins>
or when it is explicitly defaulted after its first declaration. 
</blockquote>

<p>
Change in 17.8.1 temp.inst paragraph 3:
</p>

<blockquote>
Unless a member of a class template or a member template has been explicitly
instantiated or explicitly specialized, the specialization of the member is
implicitly instantiated when the specialization is referenced in a context
that requires the member definition to exist
<ins>or if the existence of the definition of the member affects
the semantics of the program</ins>; [&hellip;]
</blockquote>

<p>
Change in 17.8.1 temp.inst paragraph 4:
</p>

<blockquote>
Unless a function template specialization has been explicitly instantiated or
explicitly specialized, the function template specialization is implicitly
instantiated when the specialization is referenced in a context that requires a
function definition to exist <ins>or if the existence of the definition affects
the semantics of the program</ins>.
A function whose declaration was instantiated from a friend function definition
is implicitly instantiated when it is referenced in a context that requires a
function definition to exist <ins>or if the existence of the definition affects
the semantics of the program</ins>.
[&hellip;]
</blockquote>

<p>
Change in 17.8.1 temp.inst paragraph 6:
</p>

<blockquote>
Unless a variable template specialization has been explicitly instantiated or
explicitly specialized, the variable template specialization is implicitly
instantiated when <del>the specialization is used</del>
<ins>it is referenced in a context that requires a variable definition
to exist or if the existence of the definition affects the semantics of
the program</ins>. A default template argument for a
variable template is implicitly instantiated when the variable template is
referenced in a context that requires the value of the default argument.
</blockquote>

<p>
Add a new paragraph after 17.8.1 temp.inst paragraph 6:
</p>

<blockquote class="stdins">
The existence of a definition of a variable or function is considered to affect
the semantics of the program if the variable or function is needed for constant
evaluation by an expression, even if constant evaluation of the expression is
not required or if constant expression evaluation does not use the definition.
[&nbsp;<i>Example</i>:
<pre>template&lt;typename T> constexpr int f() { return T::value; }
template&lt;bool B, typename T> void g(decltype(B ? f&lt;T>() : 0));
template&lt;bool B, typename T> void g(...);
template&lt;bool B, typename T> void h(decltype(int{B ? f&lt;T>() : 0}));
template&lt;bool B, typename T> void h(...);
void x() {
  g&lt;false, int>(0); // OK, B ? f&lt;T>() : 0 is not potentially constant evaluated
  h&lt;false, int>(0); // error, instantiates f&lt;int> even though B evaluates to false and
                    // list-initialization of int from int cannot be narrowing
}
</pre>
]
</blockquote>

</body></html>
