<html>
<head>
<title>P0490R0: Core language changes addressing National Body comments for CD C++17</title>

<style type="text/css">
  .new { text-decoration:none; font-weight:bold; background-color:#D0FFD0 }
  ins { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }
  strong { font-weight: inherit; color: #2020ff }
</style>
</head>

<body>
ISO/IEC JTC1 SC22 WG21 P0490R0<br/>
Jens Maurer &lt;Jens.Maurer@gmx.net><br/>
Audience: Core Working Group<br/>
2016-11-11

<h1>P0490R0: Core language changes addressing National Body comments for CD C++17</h1>

<p>
This paper presents changes to the core language sections of the C++
Working Paper
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2016/n4606.pdf">N4606</a>
in response to National Body comments in response to the Committee
Draft for C++17,
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2016/n4604.pdf">N4604</a>.


<h2>US 28: incorrect definition for principal constructor</h2>

This is a defect against C++14.
<p>

Change in 8.6 [dcl.init] paragraph 8:

<blockquote>
<del>An object that is value-initialized is deemed to be constructed and
thus subject to provisions of this International Standard applying to
"constructed" objects, objects "for which the constructor has
completed," etc., even if no constructor is invoked for the object's
initialization.</del>

</blockquote>

Add a new paragraph at the end of 8.6 [dcl.init]:

<blockquote>
<ins>An object whose initialization has completed is deemed to be
constructed, even if no constructor of the object's class is invoked
for the initialization.  [ Note: Such an object might have been
value-initialized or initialized by aggregate initialization (8.6.1
[dcl.init.aggr]) or by an inherited constructor (12.6.3
[class.inhctor.init]). -- end note ] </ins>

</blockquote>


Change in 12.6.2 [class.base.init] paragraph 6:

<blockquote>

... If a <em>mem-initializer-id</em> designates the constructor's
class, it shall be the only <em>mem-initializer</em>; the constructor
is a <em>delegating constructor</em>, and the constructor selected by
the <em>mem-initializer</em> is the <em>target constructor</em>.  <del>The
<em>principal constructor</em> is the first constructor invoked in the
construction of an object (that is, not a target constructor for that
object's construction).</del> The target constructor is selected by
overload resolution. ...

</blockquote>

Change in 12.6.3 [class.inhctor.init] paragraph 3:

<blockquote>
When an object is initialized by
an <del>inheriting</del> <ins>inherited</ins> constructor, the
<del>principal constructor (12.6.2 [class.base.init], 15.2
[except.ctor]) for the object is considered to have completed
execution</del> <ins>initialization of the object is complete</ins>
when the initialization of all subobjects is complete.

</blockquote>

Change in 15.2 [except.ctor] paragraphs 3 and 4:

<blockquote>
<del>For an object of class type of any storage duration whose</del>
<ins>If the</ins> initialization or destruction <ins>of an
object other than by a delegating constructor</ins>
is terminated by an exception, the destructor is invoked for each of
the object's <del>fully constructed</del> <ins>direct subobjects and,
for a complete object, virtual base class</ins> subobjects, <del>that
is, for each subobject for which the principal constructor (12.6.2)has
completed execution</del> <ins>whose initialization has completed (8.6
[dcl.init])</ins> and <ins>whose</ins> <del>the</del> destructor has
not yet begun execution, except that in the case of destruction, the
variant members of a union-like class are not destroyed. The
subobjects are destroyed in the reverse order of the completion of
their construction.  Such destruction is sequenced before entering a
handler of the function-try-block of the constructor or destructor, if
any.
<p>
<del>Similarly, if the principal constructor for an object has
completed execution and a delegating constructor for that object exits
with an exception, the object's destructor is invoked.</del>

 <ins>If
the <em>compound-statement</em> of the <em>function-body</em> of a
delegating constructor for an object exits via an
exception, the object's destructor is invoked.</ins>  Such destruction is
sequenced before entering a <em>handler</em> of the <em>function-try-block</em>
of a delegating constructor for that object, if any.

</blockquote>


<h2>US 93: argument evaluation order when calling an operator function</h2>

Change in 5.2.2 [expr.call] paragraph 5:

<blockquote>
The <em>postfix-expression</em> is sequenced before each expression in
the <em>expression-list</em> and any default argument. The
initialization of a parameter, including every associated value
computation and side effect, is indeterminately sequenced with respect
to that of any other parameter. [ Note: All side effects of argument
evaluations are sequenced before the function is entered (see 1.9
[intro.execution]). -- end note ] [ Example: ... ] <ins>[ Note: If an
operator function is invoked using operator notation, argument
evaluation is sequenced as specified for the built-in operator; see
13.3.1.2 [over.match.oper]. -- end note] [ Example:</ins>

<pre>
<ins>struct S {
  S(int);
};
int operator<<(S, int);
int i;
int x = S(i=1) << (i=2);
int j;
int y = operator<<(S(j=1), j=2);</ins>
</pre>

<ins> After performing the initializations, the value of
<code>i</code> is 2 (see 5.8 [expr.shift]), but it is unspecified
whether the value of <code>j</code> is 1 or 2.-- end example ]</ins>

</blockquote>

<em>Drafting note: There is no <em>expression-list</em> when using
operator notation.</em>



<h2>US 94, GB 13, FI 21: class template deduction in explicit type
conversion using a <em>braced-init-list</em></h2>

Change in 5.2.3 [expr.type.conv] paragraphs 1 and 2:

<blockquote>
A <em>simple-type-specifier</em> (7.1.7.2) or <em>typename-specifier</em> (14.6)
followed by a parenthesized optional <em>expression-list</em> or by a
<em>braced-init-list</em> (the initializer) constructs a value of the
specified type given the initializer.  <ins>If the type is a
placeholder for a deduced class type, it is replaced by the
return type of the function selected by overload resolution for class
template deduction (13.3.1.8 [over.match.class.deduct]) for the
remainder of this section.</ins>
<p>
If the initializer is a parenthesized
single expression, the type conversion expression is equivalent (in
definedness, and if defined in meaning) to the corresponding cast
expression (5.4). If the type is (possibly cv-qualified) void and the
initializer is (), the expression is a prvalue of the specified type
that performs no initialization.  Otherwise, the expression is a
prvalue of the specified type whose result object is
direct-initialized (8.6) with the initializer. For an expression of
the form T(), T shall not be an array type.

<p>
<del>A <em>template-name</em> corresponding to a class template
followed by a parenthesized <em>expression-list</em> constructs a
value of a
<del>particular</del> type determined as follows.  Given such an
expression <code>T(x1, x2, ...)</code>, construct the
declaration <code>T t(x1, x2, ...)</code>; for some invented variable
t. Define <code>U</code> to be
<code>decltype(t)</code>, then the expression <code>T(x1, x2,
...)</code> is equivalent to the expression <code>U(x1, x2,
...)</code>.</del>

</blockquote>

<em>Drafting note: Since the braced-init-list syntax for types (as
opposed to template-names) was already valid, and there is a syntax
transformation to a variable declaration, no additional ambiguities
are apparent by allowing the additional context for class template
  deduction.</em>


<h2>US 103: explicit deduction guides consider default template arguments</h2>

<em>Drafting note: 14.3 [temp.arg] p7 seems to be clear that default
arguments are considered when parsing a template-id.  Given the fact
that 14.9 [temp.deduct.guide] is devoid of any example right now, it
seems a good idea to add one.</em>

<p>

Add a new paragraph after 14.9 [temp.deduct.guide] paragraph 1:

<blockquote class="new">
[ Example:
<pre>
template&lt;class T, class D = int>
struct S {
  T data;
};
template&lt;class U>
S(U) -> S&lt;typename U::type>;

struct A {
  using type = short;
  operator type();
};
S x{A()};  // x is of type S&lt;short, int>
</pre>
-- end example ]
</blockquote>


<h2>GB 5: definition of template parameter</h2>

This is a defect against C++14.
<p>
  
Change in 1.3.17 [defns.parameter.templ]:

<blockquote>
<b>parameter</b><br/>

&lt;template>
<del><em>template-parameter</em></del> <ins>member of
a <em>template-parameter-list</em></ins>

</blockquote>


<h2>GB 6: definition of undefined behavior vs. constexpr</h2>

This is a defect against C++14.
<p>
  
Change in 1.3.25 [defns.undefined]:


<blockquote>
<b>undefined behavior</b><br/>

behavior for which this International Standard imposes no requirements
[ Note: Undefined behavior may be expected when this International
Standard omits any explicit definition of behavior or when a program
uses an erroneous construct or erroneous data. Permissible undefined
behavior ranges from ignoring the situation completely with
unpredictable results, to behaving during translation or program
execution in a documented manner characteristic of the environment
(with or without the issuance of a diagnostic message), to terminating
a translation or execution (with the issuance of a diagnostic
message).  Many erroneous program constructs do not engender undefined
behavior; they are required to be diagnosed. <ins>Evaluation of a
constant expression never exhibits behavior explicitly specified as
undefined (5.20 [expr.const]).</ins> -- end note ]

</blockquote>

Add at the end of 1.4 [intro.compliance] paragraph 4:

<blockquote>
  <ul>
    <li>...</li>
  </ul>
<ins>[ Note: During template argument deduction and substitution,
certain constructs that in other contexts require a diagnostic are treated
differently; see 14.8.2 [temp.deduct]. -- end note ]</ins>
</blockquote>


<h2>GB 19: missing cv-qualification when materializing a temporary object</h2>

Change in 8.6.3 [dcl.init.ref] paragraph 5.2.3:

<blockquote>
<ul>
<li>If the initializer expression

<ul>

<li>is an rvalue (but not a bit-field) or function lvalue and "cv1 T1"
is reference-compatible with "cv2 T2", or</li>

<li>has a class type (i.e., T2 is a class type), where T1 is not
reference-related to T2, and can be converted to an rvalue of type
"cv3 T3", where "cv1 T1" is reference-compatible with "cv3 T3" (see
13.3.1.6 [over.match.ref]),</li>

</ul>

then <del>the reference is bound to</del> the value of the initializer
expression in the first case and <del>to</del> the result of the
conversion in the second case <ins>is called the converted
initializer.  If the converted initializer is a prvalue, its type
<code>T4</code> is adjusted to type <code>cv1 T4</code> (4.5
[conv.qual]) and the temporary materialization conversion (4.4
[conv.rval]) is applied.  In any case, the reference is bound to the
resulting glvalue</ins> (or<del>, in either case,</del> to an
appropriate base class subobject) <del>after applying the temporary
materialization conversion (4.4 [conv.rval])</del>. [ Example: ... ]

</blockquote>


<h2>GB 20: decomposition declaration should commit to tuple
interpretation early</h2>

Change in 8.5 [dcl.decomp] paragraph 3:

<blockquote>
Otherwise, if <ins>the <em>qualified-id</em>
<code>std::tuple_size&lt;E></code> names a complete type,</ins> the
expression <code>std::tuple_size&lt;E>::value</code> <del>is</del>
<ins>shall be</ins> a well-formed integral constant
expression<del>,</del> <ins>and</ins> the number of elements in the
<em>identifier-list</em> shall be equal to the value of that
expression. ...

</blockquote>


<h2>GB 23: handlers taking a reference to array or function</h2>

This is a defect against C++14.
<p>
  
Change in 15.3 [except.handle] paragraph 3:

<blockquote>
[ Note: A <em>throw-expression</em> whose operand is an integer
literal with value zero does not match a handler of pointer or pointer
to member type. <ins>A handler of reference to array or function type
is never a match for any exception object (5.17 [expr.throw]).</ins>
-- end note ]

</blockquote>


<h2>GB 25: imprecise description when terminate is called</h2>

This is a defect against C++14.
<p>
  
Change in 15.1 [except.throw] paragraph 7:

<blockquote>
If the exception handling mechanism<del>, after completing the
initialization of the exception object but before the activation of a
handler for the exception, calls</del> <ins>handling an uncaught
exception (15.5.3 [except.uncaught]) directly invokes</ins> a function
that exits via an exception, <code>std::terminate</code> is called
(15.5.1 [except.terminate]). [ Example: ... ] <ins>[ Note:
Consequently, destructors should generally catch exceptions and not
let them propagate. ]</ins>

</blockquote>

Change in 15.2 [except.ctor] paragraph 1:

<blockquote>
... <del>If a destructor directly invoked by stack unwinding
exits with an exception, std::terminate is
called (15.5.1). [ Note: Consequently, destructors should generally
catch exceptions and not let them propagate out of the destructor. --
end note ]</del>

</blockquote>


<h2>GB 26: 'last' active handler and multithreading</h2>

This is a defect against C++14.
<p>

Change in 15.1 [except.throw] paragraph 4:

<blockquote>

The memory for the exception object is allocated in an unspecified
way, except as noted in 3.7.4.1 [basic.stc.dynamic.allocation]. If a
handler exits by rethrowing, control is passed to another handler for
the same exception
<ins>object</ins>. The <del>exception object is destroyed after either
the last remaining</del> <ins>points of potential destruction for the
exception object are:</ins>

<ul>
<li><ins>an</ins> active handler for the
exception exits by any means other than rethrowing<del>, or the last</del>
<ins>, immediately after the destruction of the object (if any) declared in the
<em>exception-declaration</em> in the handler;</ins>

<li><ins>an</ins> object of type <code>std::exception_ptr</code>
(18.8.6 [propagation]) that refers to the exception object is
destroyed, <ins>before the destructor of
<code>std::exception_ptr</code> returns</ins> <del>whichever is
later</del>.</li>

</ul>

<del>In the former case, the destruction occurs when the handler exits,
immediately after the destruction of the object declared in the
exception-declaration in the handler, if any. In the latter case, the
destruction occurs before the destructor of
<code>std::exception_ptr</code> returns.</del>

<ins>Among all points of potential destruction for the exception
object, there is an unspecified last one where the exception object is
destroyed. All other points happen before that last one (1.10.1
[intro.races]).  [ Note: No other thread synchronization is implied in
exception handling. ]</ins>

The implementation may then deallocate the memory for the exception
object; any such deallocation is done in an unspecified way.  [ Note:
a thrown exception does not propagate to other threads unless caught,
stored, and rethrown using appropriate library functions; see 18.8.6
and 30.6. -- end note ]

</blockquote>

<h2>GB 27: multiple activations of the same exception object</h2>

This is a defect against C++14.
<p>
  
Change in 15.5.3 [except.uncaught] paragraph 1:

<blockquote>
An exception is considered uncaught after completing the
initialization of the exception object (15.1 [except.throw]) until
completing the activation of a handler for the exception (15.3
[except.handle]). This includes stack
unwinding. If <del>the</del> <ins>an</ins> exception is rethrown
(5.17<ins>, 18.8.6 [propagation]</ins>), it is considered uncaught
from the point of rethrow until the rethrown exception is caught
<del>again</del>. The function std::uncaught_exceptions() (18.8.5
[uncaught.exceptions]) returns the number of uncaught exceptions in
the current thread.

</blockquote>


<h2>GB 63: add limit for number of lambda-captures</h2>

This is a defect against C++14.
<p>
  
Add in Annex B [implimits]:

<blockquote class="new">
<ul>
<li>Lambda-captures in one <em>lambda-expression</em> [256].</li>
</ul>
</blockquote>


<h2>GB 64: add limit for length of initializer-list</h2>

This is a defect against C++14.
<p>
  
Add in Annex B [implimits]:

<blockquote class="new">
<ul>
<li>Initializer-clauses in one <em>braced-init-list</em> [16384].</li>
</ul>
</blockquote>

<h2>GB 65: add limit for number of identifiers in decomposition declaration</h2>

Add in Annex B [implimits]:

<blockquote class="new">
<ul>
<li>Identifiers introduced in one decomposition declaration [256].</li>
</ul>
</blockquote>


<h2>FI 20: decomposition declarations with parentheses</h2>

Change in 7 [dcl.dcl]:

<blockquote>
  <pre>
    <em>simple-declaration:
      decl-specifier-seq init-declarator-list<sub>opt</sub> ;
      attribute-specifier-seq decl-specifier-seq init-declarator-list ;
      attribute-specifier-seq<sub>opt</sub> decl-specifier-seq ref-qualifier<sub>opt</sub>
            [ identifier-list ] <del>brace-or-equal-initializer</del> <ins>initializer</ins> ;</em>
</blockquote>

Change in 7 [dcl.dcl] paragraph 8:

<blockquote>
  The <del><em>brace-or-equal-initializer</em></del>
  <ins><em>initializer</em></ins> shall be of the form
  "= <em>assignment-expression</em>" <del>or</del> <ins>,</ins> of the
  form "{ <em>assignment-expression</em> }", <ins>or of the form
  "( <em>assignment-expression</em> )",</ins> where
  the <em>assignment-expression</em> is of array or non-union class
  type.
</blockquote>

Change in 8.5 [dcl.decomp] paragraph 1:

<blockquote>
If the <em>assignment-expression</em> in the
<del><em>brace-or-equal-initializer</em></del>
<ins><em>initializer</em></ins> has array type A and no <em>ref-qualifier</em>
is present, e has type cv A and each element is copy-initialized or
direct-initialized from the corresponding element of the
<em>assignment-expression</em> as specified by the form of the
<del><em>brace-or-equal-initializer</em></del> <ins><em>initializer</em></ins>. Otherwise, e is defined as-if by
<pre>
  <em>attribute-specifier-seq <sub>opt</sub> decl-specifier-seq ref-qualifier<sub>opt</sub> e <del>brace-or-equal-initializer</del> <ins>initializer</ins></em> ;
</pre>

where <ins>the declaration is never interpreted as a function
declaration and</ins> the parts of the declaration other than the
<em>declarator-id</em> are taken from the corresponding decomposition
declaration. ...

</blockquote>

<h2>RU 1: CWG 253: Why must empty or fully-initialized const objects be initialized?</h2>

This is a defect against C++14.
<p>
  
Change in 8.6 [dcl.init] paragraph 7:

<blockquote>
To <em>default-initialize</em> an object of type T means:
<ul>
<li>...</li>
<li>...</li>
<li>...</li>
</ul>

<ins>A class type T is <em>const-default-constructible</em> if
default-initialization of T would invoke a user-provided constructor
of T (not inherited from a base class) or if</ins>
<ul>
  <li><ins>each direct non-variant non-static data
  member M of T has a default member initializer or, if M is of class
  type X (or array thereof), X is const-default-constructible,
      </ins></li>
  <li><ins>if T is a union with at least one non-static data
	member, exactly one variant member has a default member
	initializer,</ins></li>
  <li><ins>if T is a not a union, for each anonymous union
	member with at least one non-static data member (if any),
	exactly one non-static data member has a default member
	initializer, and</ins></li>
   
  <li><ins>each potentially constructed base class of T is
  const-default-constructible.</ins></li>
</ul>

If a program calls for the default-initialization of an object of a
const-qualified type T, T shall be a <ins>const-default-constructible</ins>
class type <ins>or array thereof</ins> <del>with a user-provided
default constructor</del>.

</blockquote>


</body>

</html>
