<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
        "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
	<title>traits</title>
    <style type="text/css">
    p {text-align:justify}
    li {text-align:justify}
    blockquote.note
    {
        background-color:#E0E0E0;
        padding-left: 15px;
        padding-right: 15px;
        padding-top: 1px;
        padding-bottom: 1px;
    }
    ins {background-color:#A0FFA0}
    del {background-color:#FFA0A0}
    </style>
</head>
<body>

<address align=right>
Document number: N3142=10-0132<br>
<br>
<a href="mailto:jason@redhat.com">Jason Merrill</a><br>
<a href="mailto:daniel.kruegler@googlemail.com">Daniel Kr&uuml;gler</a><br>
<a href="mailto:howard.hinnant@gmail.com">Howard Hinnant</a><br>
<a href="mailto:gdr@cs.tamu.edu">Gabriel Dos Reis</a><br>

2010-10-15
</address>
<hr>
<h1 align=center>Adjustments to constructor and assignment traits</h1>

<p>
This paper proposes adjustments to the constructor and assignment traits, and
to other closely related subjects.  These changes address the following national
body comments:
</p>

<blockquote>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3118.html#DE17">DE 17</a><br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3118.html#DE18">DE 18</a><br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3118.html#GB91">GB 91</a><br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3118.html#GB92">GB 92</a><br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3118.html#FI18">FI 18</a><br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3118.html#GB50">GB 50</a><br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3118.html#GB51">GB 51</a><br/>
</blockquote>

<h2>Introduction</h2>

<p>
The library reflector thread starting with c++std-lib-28321 exposed confusion
concerning the constructor and assignment traits.  The current names lead people
to believe that the semantics of the traits should match the core language
semantics, and are confused when they don't.
</p>

<p>
But the core language semantics aren't actually very useful to a library writer;
they don't care whether or not a class has something which the core language
considers a copy constructor. They want to know if actually writing T(someT)
will work, whether it calls a copy constructor or a move constructor or a member
template constructor or whatever constructor.
</p>

<p>
This is particularly true of the "trivial" variants; it doesn't matter whether a
class has a trivial copy constructor if the constructor you actually end up
calling for a particular argument is non-trivial.
</p>

<p>
The <tt>is_constructible&lt;T, Args...&gt;</tt> trait on the other hand, is
named in such a way that conveys the semantics most useful to a library writer:
i.e. can I construct a <tt>T</tt> in this specific way.
</p>

<p>
Therefore we propose to change the names of all of the
<tt>has_*_constructor</tt> and <tt>has_*_assign</tt> traits to
<tt>is_*_constructible</tt> and <tt>is_*_assignable</tt>.  This renaming is
summarized in the following table:
</p>

<center>
<table border="3" cellpadding="2" rules=groups>
<caption>
Summary of renamed traits
</caption>

<colgroup></colgroup>
<colgroup></colgroup>
<colgroup></colgroup>
<colgroup></colgroup>

<thead>
<tr>
<th>
</th>
<th>
General form
</th>
<th>
Nothrow form
</th>
<th>
Trivial form
</th>
</tr>
</thead>

<tbody>
<tr>
<th rowspan="4">
Construction
</th>
<td>
<tt>is_constructible</tt>
</td>
<td>
<tt>is_nothrow_constructible</tt>
</td>
<td>
&nbsp;
</td>
</tr>

<tr>
<td>
<tt><del>has</del><ins>is</ins>_default_construct<ins>ible</ins><del>or</del></tt>
</td>
<td>
<tt><del>has</del><ins>is</ins>_nothrow_default_construct<ins>ible</ins><del>or</del></tt>
</td>
<td>
<tt><del>has</del><ins>is</ins>_trivial<ins>ly</ins>_default_construct<ins>ible</ins><del>or</del></tt>
</td>
</tr>

<tr>
<td>
<tt><del>has</del><ins>is</ins>_copy_construct<ins>ible</ins><del>or</del></tt>
</td>
<td>
<tt><del>has</del><ins>is</ins>_nothrow_copy_construct<ins>ible</ins><del>or</del></tt>
</td>
<td>
<tt><del>has</del><ins>is</ins>_trivial<ins>ly</ins>_copy_construct<ins>ible</ins><del>or</del></tt>
</td>
</tr>

<tr>
<td>
<tt><del>has</del><ins>is</ins>_move_construct<ins>ible</ins><del>or</del></tt>
</td>
<td>
<tt><del>has</del><ins>is</ins>_nothrow_move_construct<ins>ible</ins><del>or</del></tt>
</td>
<td>
<tt><del>has</del><ins>is</ins>_trivial<ins>ly</ins>_move_construct<ins>ible</ins><del>or</del></tt>
</td>
</tr>
</tbody>

<tbody>
<tr>
<th>
Destruction
</th>
<td>
&nbsp;
</td>
<td>
&nbsp;
</td>
<td>
<tt><del>has</del><ins>is</ins>_trivial<ins>ly</ins>_destruct<ins>ible</ins><del>or</del></tt>
</td>
</tr>
</tbody>

<tbody>
<tr>
<th rowspan="2">
Assignment
</th>
<td>
<tt><del>has</del><ins>is</ins>_copy_assign<ins>able</ins></tt>
</td>
<td>
<tt><del>has</del><ins>is</ins>_nothrow_copy_assign<ins>able</ins></tt>
</td>
<td>
<tt><del>has</del><ins>is</ins>_trivial<ins>ly</ins>_copy_assign<ins>able</ins></tt>
</td>
</tr>

<tr>
<td>
<tt><del>has</del><ins>is</ins>_move_assign<ins>able</ins></tt>
</td>
<td>
<tt><del>has</del><ins>is</ins>_nothrow_move_assign<ins>able</ins></tt>
</td>
<td>
<tt><del>has</del><ins>is</ins>_trivial<ins>ly</ins>_move_assign<ins>able</ins></tt>
</td>
</tr>
</tbody>
</table>
</center>

<p>
Furthermore, as noted in GB 92 for the "nothrow" traits, the definitions have
become redundant and confusing.  This redundancy and confusion actually extends
to nearly all of these traits, and in some cases actually leads to incorrect
definitions, or at the very least, a lack of self-consistency among the traits.
For example, as specified in the current Working Draft:
</p>

<blockquote><pre>
typedef char Array[3];
is_constructible&lt;Array, const Array&amp;&gt;::value == false
has_copy_constructor&lt;Array, const Array&amp;&gt;::value == true
</pre></blockquote>

<p>
With our proposed clarifying names, we wish for
<tt>is_copy_constructible&lt;T&gt;</tt> to have the exact same behavior as
<tt>is_constructible&lt;T, const T&amp;&gt;</tt>.  So we have adjusted the
definitions of the <tt>is_*_constructible</tt> traits to be simple synonyms
for <tt>is_constructible</tt> and similarly for the "nothrow" variants.  E.g.:
</p>

<blockquote>
<table border="1"
<tr>
<td><tt>template &lt;class T&gt; struct
<del>has_nothrow_copy_constructor</del>
<ins>is_nothrow_copy_constructible</ins>;</tt></td>
<td><del><tt>has_trivial_copy_constructor&lt;T&gt;::value</tt> is <tt>true</tt>
or <tt>is_nothrow_constructible&lt;U, const U&amp;&gt;::value</tt> is
<tt>true</tt>, where <tt>U</tt> is
<tt>remove_all_extents&lt;T&gt;::type</tt>.</del><br/>
<ins><tt>is_nothrow_constructible&lt;T, const T&amp;&gt;::value</tt> is
<tt>true</tt>.</ins>
</td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>
</table>
</blockquote>

<p>
This formulation makes it much easier to get the definitions correct.  I.e. what
it means to be "nothrow constructible" is defined in exactly one place (the
definition of <tt>is_nothrow_constructible</tt>).  The other "nothrow
constructible" traits reuse this definition as much as possible, with no
repetition.
</p>

<p>
However we note that we can not currently apply this formula to the "trivially
constructible" traits, nor to <tt>is_trivially_destructible</tt>, nor to any of
the assignable traits.  The problem is the lack of <tt>is_destructible</tt> (FI
18), lack of <tt>is_trivially_constructible</tt>, and the lack of generalized
assignable traits.  We strongly feel that this lack of completeness will
inevitably lead to situations where programmers will not be able to query or
assert properties of types necessary to the correct operation of their code. For
example a container is likely to assert that a contained type have a
non-throwing destructor. Lack of this property leads to the container's
destructor becoming a source of memory leaks.
</p>

<p>
Therefore we propose the following 6 new traits to complete the suite of traits:
</p>

<center>
<table border="3" cellpadding="2" rules=groups>
<caption>
Summary of traits, new traits shown as insertions
</caption>

<colgroup></colgroup>
<colgroup></colgroup>
<colgroup></colgroup>
<colgroup></colgroup>

<thead>
<tr>
<th>
</th>
<th>
General form
</th>
<th>
Nothrow form
</th>
<th>
Trivial form
</th>
</tr>
</thead>

<tbody>
<tr>
<th rowspan="4">
Construction
</th>
<td>
<tt>is_constructible</tt>
</td>
<td>
<tt>is_nothrow_constructible</tt>
</td>
<td>
<ins><tt>is_trivially_constructible</tt></ins>
</td>
</tr>

<tr>
<td>
<tt>is_default_constructible</tt>
</td>
<td>
<tt>is_nothrow_default_constructible</tt>
</td>
<td>
<tt>is_trivially_default_constructible</tt>
</td>
</tr>

<tr>
<td>
<tt>is_copy_constructible</tt>
</td>
<td>
<tt>is_nothrow_copy_constructible</tt>
</td>
<td>
<tt>is_trivially_copy_constructible</tt>
</td>
</tr>

<tr>
<td>
<tt>is_move_constructible</tt>
</td>
<td>
<tt>is_nothrow_move_constructible</tt>
</td>
<td>
<tt>is_trivially_move_constructible</tt>
</td>
</tr>
</tbody>

<tbody>
<tr>
<th>
Destruction
</th>
<td>
<ins><tt>is_destructible</tt></ins>
</td>
<td>
<ins><tt>is_nothrow_destructible</tt></ins>
</td>
<td>
<tt>is_trivially_destructible</tt>
</td>
</tr>
</tbody>

<tbody>
<tr>
<th rowspan="3">
Assignment
</th>
<td>
<ins><tt>is_assignable</tt></ins>
</td>
<td>
<ins><tt>is_nothrow_assignable</tt></ins>
</td>
<td>
<ins><tt>is_trivially_assignable</tt></ins>
</td>
</tr>

<tr>
<td>
<tt>is_copy_assignable</tt>
</td>
<td>
<tt>is_nothrow_copy_assignable</tt>
</td>
<td>
<tt>is_trivially_copy_assignable</tt>
</td>
</tr>

<tr>
<td>
<tt>is_move_assignable</tt>
</td>
<td>
<tt>is_nothrow_move_assignable</tt>
</td>
<td>
<tt>is_trivially_move_assignable</tt>
</td>
</tr>
</tbody>
</table>
</center>

<p>
We address GB 91 in the definition of the newly introduced <tt>is_assignable</tt>
trait, using <tt>declval</tt> as suggested.  All of the rest of the assignable
traits reuse this definition without repetition.
</p>

<p>
In addition we wish to address GB 50 and GB 51 in this paper because the topic
is intimately related to the definition of move construction and move assignment
and subsequently the <tt>is_move_constructible</tt> and
<tt>is_move_assignable</tt> traits.
</p>

<p>
The following list shows the current usages of the terms "move-construct" and
"move-assign" in the library. While some occurrences are purely descriptive
usages of these words, most of them refer to what the type traits
<tt>is_move_constructible&lt;T&gt;</tt> and <tt>is_move_assignable&lt;T&gt;</tt>
stand for. The list omits to enumerate all usages of these terms within the
definition of <tt>pair</tt> and <tt>tuple</tt>s, because those will be
completely replaced by another paper (N3140).
</p>

<ol>
<li>
<p>
Table 42, entry: <tt>X::propagate_on_container_move_assignment</tt>
</p>

<blockquote>
<tt>true_type</tt> only if an allocator of type <tt>X</tt> should be moved when
the client container is move-assigned.
</blockquote>
</li>

<li>
20.8.14.2.1/8: "otherwise, move-constructs the target"
</li>

<li>
20.9.10.2.1/14: "This <tt>unique_ptr</tt> will hold a value move constructed
from <tt>d</tt>."
</li>

<li>
20.9.10.2.1/19: "If <tt>D</tt> is a reference type, this deleter is copy
constructed from <tt>u</tt>'s deleter; otherwise, this deleter is move
constructed from <tt>u</tt>'s deleter."
</li>

<li>
20.9.10.2.1/24: "If <tt>E</tt> is a reference type, this deleter is copy
constructed from <tt>u</tt>'s deleter; otherwise, this deleter is move
constructed from <tt>u</tt>'s deleter."
</li>

<li>
20.9.11.2.1/24: "<i>Effects:</i> Move-constructs a <tt>shared_ptr</tt> instance
from <tt>r</tt>."
</li>

<li>
Table 93 &mdash; Container requirements, entry "<tt>a = rv</tt>": "All existing
elements of a are either move assigned to or destroyed"
</li>

<li>
Table 96 &mdash; Allocator-aware container requirements (continued), entry
"<tt>X(rv) X u(rv)</tt>": "Requires: move construction of <tt>A</tt> shall not
exit via an exception."
</li>

<li>
<p>
Table 96 &mdash; Allocator-aware container requirements (continued),
entry "<tt>a = rv</tt>":
</p>

<blockquote>
All existing elements of <tt>a</tt> are either move assigned to or destroyed.
</blockquote>
</li>

<li>
23.5.2.1/2: "<i>Effects:</i> Initializes <tt>comp</tt> with <tt>x</tt> and
<tt>c</tt> with <tt>y</tt> (copy constructing or move constructing as
appropriate);"
</li>

<li>
23.5.2.1/4: "<i>Effects:</i> Initializes <tt>comp</tt> with <tt>x</tt> and
<tt>c</tt> with <tt>y</tt> (copy constructing or move constructing as
appropriate);"
</li>

<li>
26.7.4/before p.1: "assigns the result to <tt>*(result + (i - first))</tt>, and
move assigns from <tt>val</tt> to <tt>acc</tt>."
</li>

<li>
27.7.1.1.1/3: "<i>Effects:</i> Move constructs from the rvalue <tt>rhs</tt>.
This is accomplished by [..]" (Defined)
</li>

<li>
27.7.1.5.1/3: "<i>Effects:</i> Move constructs from the rvalue <tt>rhs</tt> by
constructing the <tt>basic_istream</tt> base class with <tt>move(rhs)</tt>."
(Defined)
</li>

<li>
27.7.2.2/5: "<i>Effects:</i> Move constructs from the rvalue <tt>rhs</tt>. This
is accomplished by [..]" (Defined)
</li>

<li>
27.8.1.1/4: "<i>Effects:</i> Move constructs from the rvalue <tt>rhs</tt>. [..]"
(Defined)
</li>

<li>
27.8.1.2/1: "<i>Effects:</i> After the move assignment [..]" (Descriptive)
</li>

<li>
27.8.2.1/3 "Move constructs from the rvalue <tt>rhs</tt>. This is accomplished
by move constructing the base class, and the contained <tt>basic_stringbuf</tt>.
[..]"
</li>

<li>
27.8.3.2/1 "<i>Effects:</i> Move assigns the base and members of <tt>*this</tt>
from the base and corresponding members of <tt>rhs</tt>."
</li>

<li>
27.8.5/3: "Move constructs from the rvalue <tt>rhs</tt>. This is accomplished by
move constructing the base class, and the contained <tt>basic_stringbuf</tt>.
[..]"
</li>

<li>
27.8.5.1/1: "<i>Effects:</i> Move assigns the base and members of <tt>*this</tt>
from the base and corresponding members of <tt>rhs</tt>."
</li>

<li>
27.9.1.2/3: "<i>Effects:</i> Move constructs from the rvalue <tt>rhs</tt>."
(Descriptive)
</li>

<li>
27.9.1.3/1: "<i>Effects:</i> Calls <tt>this-&gt;close()</tt> then move assigns
from <tt>rhs</tt>." (Descriptive)
</li>

<li>
27.9.1.7/4: "<i>Effects:</i> Move constructs from the rvalue <tt>rhs</tt>. This
is accomplished by move constructing the base class, and the contained
<tt>basic_filebuf</tt>. [..]"
</li>

<li>
27.9.1.8/1: "<i>Effects:</i> Move assigns the base and members of <tt>*this</tt>
from the base and corresponding members of <tt>rhs</tt>." (Descriptive)
</li>

<li>
27.9.1.11/4: "<i>Effects:</i> Move constructs from the rvalue <tt>rhs</tt>. This
is accomplished by move constructing the base class, and the contained
<tt>basic_filebuf</tt>. [..]"
</li>

<li>
27.9.1.12/1 "<i>Effects:</i> Move assigns the base and members of <tt>*this</tt>
from the base and corresponding members of <tt>rhs</tt>."
</li>

<li>
27.9.1.15/4: "<i>Effects:</i> Move constructs from the rvalue <tt>rhs</tt>. This
is accomplished by move constructing the base class, and the contained
<tt>basic_filebuf</tt>. [..]"
</li>

<li>
27.9.1.16/1: "<i>Effects:</i> Move assigns the base and members of
<tt>*this</tt> from the base and corresponding members of <tt>rhs</tt>."
</li>

<li>
28.8.2/12: "<i>Effects:</i> Move constructs an object of class
<tt>basic_regex</tt> from <tt>e</tt>." (Descriptive)
</li>

<li>
28.8.3/9: "<i>Effects:</i> move assigns from that into <tt>*this</tt> and
returns <tt>*this</tt>." (Descriptive)
</li>

<li>
28.10.1/5: "<i>Effects:</i> Move-constructs an object of class
<tt>match_results</tt> from m satisfying the same postconditions as Table 138."
(Descriptive) "Additionally, the stored <tt>Allocator</tt> value is move
constructed from <tt>m.get_allocator()</tt>." (Defined meaning)
</li>

<li>
28.10.1/8: "<i>Effects:</i> Move-assigns <tt>m</tt> to <tt>*this</tt>. The
postconditions of this function are indicated in Table 138." (Descriptive)
</li>

<li>
30.6.6/7: "<i>Effects:</i> move constructs a future object that refers to the
associated asynchronous state that was originally referred to by <tt>rhs</tt>
(if any)." (Descriptive)
</li>

<li>
30.6.7/10: "<i>Effects:</i> move constructs a <tt>shared_future</tt> object that
refers to the associated asynchronous state that was originally referred to by
<tt>rhs</tt> (if any)." (Descriptive)
</li>
</ol>

<h2>Proposed Wording</h2>

<ol>

<li>
<p>
Insert a new definition just before [defns.move.assign]:
</p>

<blockquote>
<table width="80%">
<tr>
<th><ins>17.3.??</ins></th> <th align="right"><ins>[defns.move.constr]</ins></th>
</tr>
<tr>
<th><ins>move construction</ins></th><td></td>
</tr>
<tr>
<td colspan="2"><ins>Direct-initialization of an object of some type with an
rvalue of the same type.</ins></td>
</tr>
</table>
</blockquote>
</li>

<li>
<p>
Change [defns.move.assign] as indicated. We disagree with the NB comment
suggestion GB 50 to add a cross-reference to (12.8). The reason is that as of
the recent core wording changes move and copy special member functions rely on
overload resolution. Second, even if we use the proper initialization or
assignment syntax with an rvalue (e.g. via <tt>std::move</tt>) this won't
guarantee that a corresponding move operation is really called. If absent, a
copy operation will be considered. Therefore we suggest to add definitions that
are more in agreement with the expression-based approach also used for the
traits definitions:
</p>

<blockquote>
<table width="80%">
<tr>
<th>17.3.12</th> <th align="right">[defns.move.assign]</th>
</tr>
<tr>
<th>move assignment</th><td></td>
</tr>
<tr>
<td colspan="2"><del>use of a move assignment operator</del> <ins>Assignment
operation of an rvalue of some object type to an modifiable lvalue of the same
type.</ins>.</td>
</tr>
</table>
</blockquote>
</li>

<li>
<p>
Remove the following two definitions. They are superfluous in agreement with the
NB comments GB 50+GB 51:
</p>

<blockquote>
<table width="80%">
<tr>
<th><del>17.3.13</del></th> <th align="right"><del>[defns.move.assign.op]</del></th>
</tr>
<tr>
<th><del>move assignment operator</del></th><td></td>
</tr>
<tr>
<td colspan="2"><del>an assignment operator which accepts only an rvalue
argument of the type being assigned to and might modify the argument as a side
effect during the assignment.</del></td>
</tr>

<tr><td>&nbsp;</td><td></td></tr>

<tr>
<th><del>17.3.14</del></th> <th align="right"><del>[defns.move.ctor]</del></th>
</tr>
<tr>
<th><del>move constructor</del></th><td></td>
</tr>
<tr>
<td colspan="2"><del>a constructor which accepts only an rvalue argument of the
type being constructed and might modify the argument as a side effect during
construction.</del></td>
</tr>

</table>
</blockquote>
</li>

<li>

<p>
Change the signature of <tt>move_if_noexcept</tt> in the synopsis in 20.3
[utility] and in 20.3.3 [forward]:
</p>

<blockquote><pre>
template &lt;class T&gt;
typename conditional&lt;
    <del>!has_nothrow_move_constructor&lt;T&gt;::value &amp;&amp; has_copy_constructor&lt;T&gt;::value,</del>
    <ins>!is_nothrow_move_constructible&lt;T&gt;::value &amp;&amp; is_copy_constructible&lt;T&gt;::value,</ins>
    const T&amp;,
    T&amp;&amp;
&gt;::type
move_if_noexcept(T&amp; x);
</pre></blockquote>

</li>

<li>
<p>
Update the synopsis in 20.7.2 [meta.type.synop] as indicated.  We suggest a
slight reordering of two traits in the header synopsis to make all three groups
consistent as shown below.
</p>

<blockquote><pre>
template &lt;class T, class... Args&gt; struct is_constructible;
<del>template &lt;class T, class... Args&gt; struct is_nothrow_constructible;</del>
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_default_construct<ins>ible</ins><del>or</del>;
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_copy_construct<ins>ible</ins><del>or</del>;
<ins>template &lt;class T&gt;                struct is_move_constructible;</ins>
<ins>template &lt;class T, class U&gt;       struct is_assignable;</ins>
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_copy_assign<ins>able</ins>;
<del>template &lt;class T&gt;                struct has_move_constructor</del>;
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_move_assign<ins>able</ins>;
<ins>template &lt;class T&gt;                struct is_destructible;</ins>

<ins>template &lt;class T, class... Args&gt; struct is_trivially_constructible;</ins>
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_trivial<ins>ly</ins>_default_construct<ins>ible</ins><del>or</del>;
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_trivial<ins>ly</ins>_copy_construct<ins>ible</ins><del>or</del>;
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_trivial<ins>ly</ins>_move_construct<ins>ible</ins><del>or</del>;
<ins>template &lt;class T, class U&gt;       struct is_trivially_assignable;</ins>
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_trivial<ins>ly</ins>_copy_assign<ins>able</ins>;
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_trivial<ins>ly</ins>_move_assign<ins>able</ins>;
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_trivial<ins>ly</ins>_destruct<ins>ible</ins><del>or</del>;

<ins>template &lt;class T, class... Args&gt; struct is_nothrow_constructible;</ins>
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_nothrow_default_construct<ins>ible</ins><del>or</del>;
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_nothrow_copy_construct<ins>ible</ins><del>or</del>;
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_nothrow_move_construct<ins>ible</ins><del>or</del>;
<ins>template &lt;class T, class U&gt;       struct is_nothrow_assignable;</ins>
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_nothrow_copy_assign<ins>able</ins>;
template &lt;class T&gt;                struct <del>has</del><ins>is</ins>_nothrow_move_assign<ins>able</ins>;
<ins>template &lt;class T&gt;                struct is_nothrow_destructible;</ins>
</pre></blockquote>
</li>

<li>

<p>
Modify Table 45 &mdash; Type property predicates in 20.7.4.3 [meta.unary.prop]
as indicated.  The table has been reordered consistent with the synopsis.
<i>[Rationale: Text presented like this in the table is intended to be rationale
for the change, and should not be put into the working paper.]</i>
</p>

<blockquote>
<table border="1" cellpadding="5">
<caption>Table 45 &mdash; Type property predicates</caption>

<tr>
<th>Template</th>
<th>Condition</th>
<th>Preconditions</th>
</tr>

<tr>
<td colspan="3" align="center">...</td>
</tr>

<tr>
<td><tt>template &lt;class T, class... Args&gt; struct
is_constructible;</tt></td>
<td><i>see below</i></td>
<td><tt>T</tt> and all types in the parameter pack <tt>Args</tt> shall be
complete types, (possibly cv-qualified) <tt>void</tt>, or arrays of unknown
bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct <del>has_default_constructor</del>
<ins>is_default_constructible</ins>;</tt></td>
<td><tt>is_constructible&lt;<del>U</del><ins>T</ins>&gt;::value</tt> is
<tt>true</tt><del>, where <tt>U</tt> is
<tt>remove_all_extents&lt;T&gt;::type</tt></del>.
<br/><br/><i>[Rationale: There is no need to treat array types specially. 
Arrays can be default constructible as defined by
<tt>is_constructible&lt;T&gt;</tt>]</i></td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct <del>has_copy_constructor</del>
<ins>is_copy_constructible</ins>;</tt></td>
<td><tt>is_constructible&lt;<del>U</del><ins>T</ins>, const
<del>U</del><ins>T</ins>&amp;&gt;::value</tt> is <tt>true</tt><del>,
where <tt>U</tt> is
<tt>remove_all_extents&lt;T&gt;::type</tt></del>.
<br/><br/><i>[Rationale: There is no need to treat array types specially. Arrays
are never copy constructible as defined by <tt>is_constructible&lt;T, const
T&amp;&gt;</tt>]</i></td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct <del>has_move_constructor</del>
<ins>is_move_constructible</ins>;</tt></td>
<td><tt>is_constructible&lt;<del>U</del><ins>T</ins>,
<del>U</del><ins>T</ins>&amp;&amp;&gt;::value</tt> is
<tt>true</tt><del>, where <tt>U</tt> is
<tt>remove_all_extents&lt;T&gt;::type</tt></del>.
<br/><br/><i>[Rationale: There is no need to treat array types specially. Arrays
are never move constructible as defined by <tt>is_constructible&lt;T,
T&amp;&amp;&gt;</tt>]</i></td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><ins><tt>template &lt;class T, class U&gt; struct
is_assignable;</tt></ins></td>
<td><ins>The expression <tt>declval&lt;T&gt;() = declval&lt;U&gt;()</tt> is
well-formed when treated as an unevaluated operand (Clause 5).  Access checking
is performed as if in a context unrelated to <tt>T</tt> and <tt>U</tt>. Only the
validity of the immediate context of the assignment expression is considered.
[<i>Note:</i> The compilation of the expression can result in side effects such
as the instantiation of class template specializations and/or function template
specializations, the generation of implicitly-defined functions, etc. Such side
effects are not in the "immediate context" and can result in the program being
ill-formed. &mdash; <i>end note</i>]</ins>
<br/><br/><i>[Rationale:  Addresses GB 91 with the use of <tt>declval</tt>.
Addresses the same concern DE 17 has with <tt>is_constructible</tt> and
<tt>is_convertible</tt>. Addresses DE 18 with a detailed description of access
checking.  Due to the extensive reuse of <tt>is_assignable</tt> for the other
assignable traits, the introduction of this trait automatically fixes all of the
assignable traits with respect to GB 91,  DE 17 and DE 18.]</i></td>
<td><ins><tt>T</tt> and <tt>U</tt> shall be complete types, (possibly
cv-qualified) <tt>void</tt>, or arrays of unknown bound.</ins></td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct <del>has_copy_assign</del>
<ins>is_copy_assignable</ins>;</tt></td>
<td><del><tt>T</tt> is neither <tt>const</tt> nor a reference type, and
<tt>T</tt> is a trivial type (3.9) or the expression <tt>*(U*)0 =
declval&lt;const U&amp;&gt;()</tt> is well-formed when treated as an unevaluated
operand (Clause 5), where <tt>U</tt> is
<tt>remove_all_extents&lt;T&gt;::type</tt>.</del>
<ins><tt>is_assignable&lt;T&amp;, const T&amp;&gt;::value</tt> is
<tt>true</tt>.</ins>
<br/><br/><i>[Rationale:  Addresses GB 91, DE 17 and DE 18 by reusing
<tt>is_assignable</tt>.]</i></td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct <del>has_move_assign</del>
<ins>is_move_assignable</ins>;</tt></td>
<td><del><tt>T</tt> is neither <tt>const</tt> nor a reference type, and
<tt>T</tt> is a trivial type (3.9) or the expression <tt>*(U*)0 =
declval&lt;U&gt;()</tt> is well-formed when treated as an unevaluated operand
(Clause 5), where <tt>U</tt> is
<tt>remove_all_extents&lt;T&gt;::type</tt>.</del>
<ins><tt>is_assignable&lt;T&amp;, T&amp;&amp;&gt;::value</tt> is
<tt>true</tt>.</ins>
<br/><br/><i>[Rationale:  Addresses GB 91, DE 17 and DE 18 by reusing
<tt>is_assignable</tt>.]</i></td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><ins><tt>template &lt;class T&gt; struct
is_destructible;</tt></ins></td>
<td><ins>For a complete type <tt>T</tt> and given <tt>template &lt;class T&gt;
struct test {T t;};</tt>, <tt>test&lt;T&gt;::~test()</tt> is not
deleted.</ins>
<br/><br/><i>[Rationale:  Partially addresses FI 18, and addresses the same
access concern DE 18 has with the existing traits.  By addressing DE 18 once
here, and having the other destructible traits reuse this definition, DE 18 is
addressed automatically for the other destructible traits.]</i></td>
<td><ins><tt>T</tt> shall be a complete type, (possibly cv-qualified)
<tt>void</tt>, or an array of unknown bound.</ins></td>
</tr>

<tr>
<td><ins><tt>template &lt;class T, class... Args&gt; struct
is_trivially_constructible;</tt></ins></td>
<td><ins><tt>is_constructible&lt;T, Args...&gt;::value</tt> is <tt>true</tt> and
the variable definition for <tt>is_constructible</tt>, as defined below, is known
to call no operation that is not trivial (3.9 [basic.types], 12 [special]).</ins>
<br/><br/><i>[Rationale:  Serves to define the common characteristics of all of
the "trivially constructible" traits in one place.  Reuses
<tt>is_constructible</tt> so as to address the concerns of DE 17 and DE
18.]</i></td>
<td><ins><tt>T</tt> and all types in the parameter pack <tt>Args</tt> shall be
complete types, (possibly cv-qualified) <tt>void</tt>, or arrays of unknown
bound.</ins></td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct
<del>has_trivial_default_constructor</del>
<ins>is_trivially_default_constructible</ins>;</tt></td>
<td><del><tt>T</tt> is a trivial type (3.9) or a class type with a trivial
default constructor (12.1) or an array of such a class type.</del>
<ins><tt>is_trivially_constructible&lt;T&gt;::value</tt> is <tt>true</tt>.</ins>
<br/><br/><i>[Rationale:  Reuses <tt>is_trivially_constructible</tt> so as to
address the concerns of DE 17 and DE 18.]</i></td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct
<del>has_trivial_copy_constructor</del>
<ins>is_trivially_copy_constructible</ins>;</tt></td>
<td><del><tt>T</tt> is a trivial type (3.9) or a reference type or a class type
whose copy constructors (12.8) are all trivial.</del>
<ins><tt>is_trivially_constructible&lt;T, const T&amp;&gt;::value</tt> is
<tt>true</tt>.</ins>
<br/><br/><i>[Rationale:  Reuses <tt>is_trivially_constructible</tt> so as to
address the concerns of DE 17 and DE 18.]</i></td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct
<del>has_trivial_move_constructor</del>
<ins>is_trivially_move_constructible</ins>;</tt></td>
<td><del><tt>T</tt> is a trivial type (3.9) or a reference type or a class type
whose move constructors (12.8) are all trivial.</del>
<ins><tt>is_trivially_constructible&lt;T, T&amp;&amp;&gt;::value</tt> is
<tt>true</tt>.</ins>
<br/><br/><i>[Rationale:  Reuses <tt>is_trivially_constructible</tt> so as to
address the concerns of DE 17 and DE 18.]</i></td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><ins><tt>template &lt;class T, class U&gt; struct
is_trivially_assignable;</tt></ins></td>
<td><ins><tt>is_assignable&lt;T, U&gt;::value</tt> is <tt>true</tt> and the
assignment, as defined by <tt>is_assignable</tt>, is known to call no operation
that is not trivial (3.9 [basic.types], 12 [special]).</ins>
<br/><br/><i>[Rationale:  Reuses <tt>is_assignable</tt> so as to
address the concerns of GB 91, DE 17 and DE 18.]</i></td>
<td><ins><tt>T</tt> and <tt>U</tt> shall be complete types, (possibly
cv-qualified) <tt>void</tt>, or arrays of unknown bound.</ins></td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct
<del>has_trivial_copy_assign</del>
<ins>is_trivially_copy_assignable</ins>;</tt></td>
<td><del><tt>T</tt> is neither <tt>const</tt> nor a reference type, and
<tt>T</tt> is a trivial type (3.9) or a class type whose copy assignment
operators (12.8) are all trivial.</del>
<ins><tt>is_trivially_assignable&lt;T&amp;, const T&amp;&gt;::value</tt> is
<tt>true</tt>.</ins>
<br/><br/><i>[Rationale:  Reuses <tt>is_trivially_assignable</tt> so as to
address the concerns of GB 91, DE 17 and DE 18.]</i></td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct
<del>has_trivial_move_assign</del>
<ins>is_trivially_move_assignable</ins>;</tt></td>
<td><del><tt>T</tt> is neither <tt>const</tt> nor a reference type, and
<tt>T</tt> is a trivial type (3.9) or a class type whose move assignment
operators (12.8) are all trivial.</del>
<ins><tt>is_trivially_assignable&lt;T&amp;, T&amp;&amp;&gt;::value</tt> is
<tt>true</tt>.</ins>
<br/><br/><i>[Rationale:  Reuses <tt>is_trivially_assignable</tt> so as to
address the concerns of GB 91, DE 17 and DE 18.]</i></td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct <del>has_trivial_destructor</del>
<ins>is_trivially_destructible</ins>;</tt></td>
<td><del><tt>T</tt> is a trivial type (3.9) or a reference type or a class type
with a trivial destructor (12.4) or an array of such a class type.</del>
<ins><tt>is_destructible&lt;T&gt;::value</tt> is <tt>true</tt> and the indicated
destructor is known to be trivial.</ins>
<br/><br/><i>[Rationale:  Reuses <tt>is_destructible</tt> so as to
address the concerns of DE 18.]</i></td>
<td><tt>T</tt> shall be a complete type, (possibly cv-qualified) <tt>void</tt>,
or an array of unknown bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T, class... Args&gt; struct
is_nothrow_constructible;</tt></td>
<td><tt>is_constructible&lt;T, Args...&gt;::value</tt> is <tt>true</tt> and the
variable definition for <tt>is_constructible</tt>, as defined below, is known
not to throw any exceptions <ins>(5.3.7 [expr.unary.noexcept])</ins>.
<br/><br/><i>[Rationale:
We rely on the core language meaning here and therefore suggest to add a
reference to 5.3.7 [expr.unary.noexcept], because this allows us to implicitly
point to the noexcept operator as a tool to recognize this property in
situations where expressions are involved. Some type traits are defined in terms
of variable definitions and we therefore cannot directly use the operator for
them. A correct implementation will be based on a compiler-intrinsic here,
simulating implementations will typically partition into different expressions,
each of them could be checked via noexcept.
<br/>
Referring to 5.3.7 [expr.unary.noexcept] has the advantage that this sub-clause
directly refers to 15.1 [except.throw] where we find
<blockquote>
Throwing an exception transfers control to a handler.
</blockquote>
In the context we use the term it is clear that this means that the final
handler is not located within the expression or definition that is the result of
an exception.
]</i></td>
<td><tt>T</tt> and all types in the parameter pack <tt>Args</tt> shall be
complete types, (possibly cv-qualified) <tt>void</tt>, or arrays of unknown
bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct
<del>has_nothrow_default_constructor</del>
<ins>is_nothrow_default_constructible</ins>;</tt></td>
<td><del><tt>has_trivial_default_constructor&lt;T&gt;::value</tt> is
<tt>true</tt> or <tt>is_nothrow_constructible&lt;U&gt;::value</tt> is
<tt>true</tt>, where <tt>U</tt> is
<tt>remove_all_extents&lt;T&gt;::type</tt>.</del>
<ins><tt>is_nothrow_constructible&lt;T&gt;::value</tt> is <tt>true</tt>.</ins>
<br/><br/><i>[Rationale: Reuses <tt>is_nothrow_constructible</tt> so as to get
the details of the "no throw" characteristic correct and defined in only one
place.  Addresses GB 92 by removing the redundant and confusing reference to
<tt>has_trivial_default_constructor</tt>.  There is no need to treat array
types specially.]</i>
</td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct
<del>has_nothrow_copy_constructor</del>
<ins>is_nothrow_copy_constructible</ins>;</tt></td>
<td><del><tt>has_trivial_copy_constructor&lt;T&gt;::value</tt> is <tt>true</tt>
or <tt>is_nothrow_constructible&lt;U, const U&amp;&gt;::value</tt> is
<tt>true</tt>, where <tt>U</tt> is
<tt>remove_all_extents&lt;T&gt;::type</tt>.</del>
<ins><tt>is_nothrow_constructible&lt;T, const T&amp;&gt;::value</tt> is
<tt>true</tt>.</ins>
<br/><br/><i>[Rationale: Reuses <tt>is_nothrow_constructible</tt> so as to get
the details of the "no throw" characteristic correct and defined in only one
place.  Addresses GB 92 by removing the redundant and confusing reference to
<tt>has_trivial_copy_constructor</tt>.  There is no need to treat array
types specially.  Array types are never copy constructible.]</i>
</td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct
<del>has_nothrow_move_constructor</del>
<ins>is_nothrow_move_constructible</ins>;</tt></td>
<td><del><tt>has_trivial_move_constructor&lt;T&gt;::value</tt> is <tt>true</tt>
or <tt>is_nothrow_constructible&lt;U, U&amp;&amp;&gt;::value</tt> is
<tt>true</tt>, where <tt>U</tt> is
<tt>remove_all_extents&lt;T&gt;::type</tt>.</del>
<ins><tt>is_nothrow_constructible&lt;T, T&amp;&amp;&gt;::value</tt> is
<tt>true</tt>.</ins>
<br/><br/><i>[Rationale: Reuses <tt>is_nothrow_constructible</tt> so as to get
the details of the "no throw" characteristic correct and defined in only one
place.  Addresses GB 92 by removing the redundant and confusing reference to
<tt>has_trivial_move_constructor</tt>.  There is no need to treat array
types specially.  Array types are never move constructible.]</i>
</td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><ins><tt>template &lt;class T, class U&gt; struct
is_nothrow_assignable;</tt></ins></td>
<td><ins><tt>is_assignable&lt;T, U&gt;::value</tt> is <tt>true</tt> and the
assignment is known not to throw any exceptions (5.3.7
[expr.unary.noexcept]).</ins>
<br/><br/><i>[Rationale: Reuses <tt>is_assignable</tt> to address GB 91, GB 92,
DE 17 and DE 18.  References [expr.unary.noexcept] for the same reasons as
stated for <tt>is_nothrow_constructible</tt>.]</i>
</td>
<td><ins><tt>T</tt> and <tt>U</tt> shall be complete types, (possibly
cv-qualified) <tt>void</tt>, or arrays of unknown bound.</ins></td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct
<del>has_nothrow_copy_assign</del>
<ins>is_nothrow_copy_assignable</ins>;</tt></td>
<td><del><tt>has_trivial_copy_assign&lt;T&gt;::value</tt> is <tt>true</tt> or
the expression <tt>noexcept(*(U*)0 = declval&lt;const U&amp;&gt;())</tt> is
well-formed and <tt>true</tt>, where <tt>U</tt> is
<tt>remove_all_extents&lt;T&gt;::type</tt>.</del>
<ins><tt>is_nothrow_assignable&lt;T&amp;, const T&amp;&gt;::value</tt> is
<tt>true</tt>.</ins>
<br/><br/><i>[Rationale: Reuses <tt>is_nothrow_assignable</tt> to address GB 91,
GB 92, DE 17 and DE 18 and to get the details of the "no throw" characteristic
correct and defined in only one place.]</i>
</td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><tt>template &lt;class T&gt; struct
<del>has_nothrow_move_assign</del>
<ins>is_nothrow_move_assignable</ins>;</tt></td>
<td><del><tt>has_trivial_move_assign&lt;T&gt;::value</tt> is <tt>true</tt> and
<tt>T</tt> is a trivial type (3.9) or the expression <tt>noexcept(*(U*)0 =
declval&lt;U&gt;())</tt> is well-formed and <tt>true</tt>, where <tt>U</tt> is
<tt>remove_all_extents&lt;T&gt;::type</tt>.</del>
<ins><tt>is_nothrow_assignable&lt;T&amp;, T&amp;&amp;&gt;::value</tt> is
<tt>true</tt>.</ins>
<br/><br/><i>[Rationale: Reuses <tt>is_nothrow_assignable</tt> to address GB 91,
GB 92, DE 17 and DE 18 and to get the details of the "no throw" characteristic
correct and defined in only one place.]</i>
</td>
<td><tt>T</tt> shall be a complete type, (possibly <i>cv</i>-qualified)
<tt>void</tt>, or an array of unknown bound.</td>
</tr>

<tr>
<td><ins><tt>template &lt;class T&gt; struct
is_nothrow_destructible;</tt></ins></td>
<td><ins><tt>is_destructible&lt;T&gt;::value</tt> is <tt>true</tt> and the
indicated destructor is known to not throw any exceptions (5.3.7
[expr.unary.noexcept]).</ins>
<br/><br/><i>[Rationale:  Addresses FI 18.  Reuses <tt>is_destructible</tt> to
address DE 18.  References [expr.unary.noexcept] for the same reasons as stated
for <tt>is_nothrow_constructible</tt>.]</i>
</td>
<td><ins><tt>T</tt> shall be a complete type, (possibly cv-qualified)
<tt>void</tt>, or an array of unknown bound.</ins></td>
</tr>

<tr>
<td colspan="3" align="center">...</td>
</tr>

</table>

<p>4 ...</p>
<p>5 ...</p>

<p>
6 Given the following function prototype:
</p>

<blockquote><pre>
template &lt;class T&gt;
  typename add_rvalue_reference&lt;T&gt;::type create();
</pre></blockquote>

<p>
the predicate condition for a template specialization <tt>is_constructible&lt;T,
Args...&gt;</tt> shall be satisfied if and only if the following variable
definition would be well-formed <ins>for some invented variable
<tt>t</tt></ins>:
</p>

<blockquote><pre>
T t(create&lt;Args&gt;()...);
</pre></blockquote>

<p>
[<i>Note:</i> these tokens are never interpreted as a function declaration.
&mdash; <i>end note</i>] <ins>Access checking is performed as if in a context
unrelated to <tt>T</tt> and any of the <tt>Args</tt>. Only the validity of the
immediate context of the variable initialization is considered. [<i>Note:</i>
The evaluation of the initialization can result in side effects such as the
instantiation of class template specializations and/or function template
specializations, the generation of implicitly-defined functions, etc. Such side
effects are not in the "immediate context" and can result in the program being
ill-formed. &mdash; <i>end note</i>]</ins>
</p>

</blockquote>

<p>
<i>[Rationale: The words used above for <tt>is_constructible</tt>, and also
below for <tt>is_convertible</tt> address both DE 17 and DE 18.  Due to the
extensive reuse of <tt>is_constructible</tt> for the other constructible traits,
the fix for <tt>is_constructible</tt> automatically fixes all of the
constructible traits with respect to DE 17 and DE 18.]</i>
</p>

</li>

<li>

<p>
Modify Table 47 &mdash; Type relationship predicates in 20.7.5 [meta.rel]
as indicated:
</p>

<blockquote>
<table border="1">
<caption>Table 47 &mdash; Type relationship predicates</caption>

<tr>
<th>Template</th>
<th>Condition</th>
<th>Comments</th>
</tr>

<tr>
<td colspan="3" align="center">...</td>
</tr>

<tr>
<td><tt>template &lt;class From, class To&gt; struct is_convertible;</tt></td>
<td><i>see below</i></td>
<td><tt>From</tt> and <tt>To</tt> shall be complete types, arrays of unknown
bound, or (possibly cv-qualified) <tt>void</tt> types.</td>
</tr>

</table>

<p>3 ...</p>

<p>
4 Given the following function prototype:
</p>

<blockquote><pre>
template &lt;class T&gt;
  typename add_rvalue_reference&lt;T&gt;::type create();
</pre></blockquote>

<p>
the predicate condition for a template specialization
<tt>is_convertible&lt;From, To&gt;</tt> shall be satisfied if and only if the
return expression in the following code would be well-formed, including any
implicit conversions to the return type of the function:
</p>

<blockquote><pre>
To test() {
  return create&lt;From&gt;();
}
</pre></blockquote>

<p>
[<i>Note:</i> This requirement gives well defined results for reference types,
void types, array types, and function types. &mdash; <i>end note</i>]
<ins>Access checking is performed as if in a context unrelated to <tt>To</tt>
and <tt>From</tt>. Only the validity of the immediate context of the expression
of the return-statement (including conversions to the return type) is
considered. [<i>Note:</i> The evaluation of the conversion can result in side
effects such as the instantiation of class template specializations and/or
function template specializations, the generation of implicitly-defined
functions, etc. Such side effects are not in the "immediate context" and can
result in the program being ill-formed. &mdash; <i>end note</i>]</ins>
</p>

</blockquote>

</li>

</ol>

<h2>Acknowledgements</h2>

<p>
Many thanks to Jens Maurer for his generous and insightful contributions.
</p>

</body>
</html>
