<html>
<head>
<title>Minor Modifications to type traits Wording</title>
<style>
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:#FFFFA0}
del {background-color:#FFFFA0}
</style>
</head>

<body>

<address align=right>
Document number: N2157=07-0017<br>
<br>
<a href="mailto:howard.hinnant@gmail.com">Howard E. Hinnant</a><br>

2007-01-12
</address>
<hr>
<h1 align=center>Minor Modifications to the type traits Wording</h1>

<h2 align=center>Revision 1</h2>

<p>
This paper represents minor corrections to
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n2028.html">N2028</a>.
More motivation for these changes has also been included.
</p>

<h2>Contents</h2>

<ul>
<li><a href="#Introduction">Introduction</a></li>
<li>
<a href="#meta">20.4 Metaprogramming and type traits</a>
<ul>
<li><a href="#req">20.4.1 Requirements</li>
<li><a href="#synop">20.4.2 Header <tt>&lt;type_traits&gt;</tt> synopsis</a></li>
<li><a href="#help">20.4.3 Helper classes</a></li>
<li>
<a href="#class">20.4.4 Type classification traits</a>
<ul>
<li><a href="#prim">20.4.4.1 Primary classification traits</a></li>
<li><a href="#sec">20.4.4.2 Secondary classification traits</a></li>
</ul>
</li>
<li>
<a href="#prop">20.4.5 Type properties and transformations</a>
<ul>
<li><a href="#cv">20.4.5.1 Const-volatile properties and transformations</a></li>
<li><a href="#ref">20.4.5.2 Reference transformations</a></li>
<li><a href="#ptr">20.4.5.3 Pointer transformations</a></li>
<li><a href="#int">20.4.5.4 Scalar properties and transformations</a></li>
<li><a href="#arr">20.4.5.5 Array properties and transformations</a></li>
<li><a href="#intr">20.4.5.6 Member introspection</a></li>
<li><a href="#rel">20.4.5.7 Relationships between types</a></li>
<li><a href="#algn">20.4.5.8 Alignment properties and transformations</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#ack">Acknowledgments</a></li>
</ul>

<h2><a name="Introduction"></a>Introduction</h2>

<p>
Here is a concise list of problems with the current WP definition of the type traits library.
The list is ordered most important first.
</p>

<ol>
<li>The "permission to get it wrong" needs to be removed. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#590">LWG issue 590</a></li>
<li>The WP allows client-defined specializations of various traits such as <tt>is_base_of</tt> and
<tt>is_convertible</tt>, <tt>is_const</tt>, etc.  This is counter to the intent of
the type traits library.</li>
<li><tt>add_reference</tt> does not handle <tt>void</tt> types.</li>
<li><tt>add_reference</tt> needs to be split into two new traits: <tt>add_lvalue_reference</tt>
and <tt>add_rvalue_reference</tt>.</li>
<li><tt>is_reference</tt> is no longer a primary classification trait.</li>
<li><tt>is_lvalue_reference</tt> is missing.</li>
<li><tt>is_rvalue_reference</tt> is missing.</li>
<li>The <i>UnaryTypeTrait</i> and <i>BinaryTypeTrait</i> are not required to be <tt>CopyConstructible</tt> and yet
this is one of the most needed requirements.</li>
<li>The <i>UnaryTypeTrait</i> and <i>BinaryTypeTrait</i> are not required to derived
publicly from <tt>integral_constant</tt> and yet this is one of the most needed
requirements.</li>
<li>It is not clear how <tt>has_trivial_*</tt> traits works for scalar types, especially with respect
to cv-qualified types.</li>
<li>It is not clear how <tt>has_nothrow_*</tt> traits works for scalar types.</li>
<li>All of the traits labeled herein as <i>Member introspection</i> traits needlessly fail with
a compile time error for <tt>void</tt> types and arrays of unknown bounds.</li>
<li><tt>is_pointer</tt> mistakenly answers <tt>false</tt> for pointers to static members.</li>
<li><tt>is_member_object_pointer</tt> mistakenly answers <tt>true</tt> for static data members.</li>
<li><tt>is_member_function_pointer</tt> mistakenly answers <tt>true</tt> for static member functions.</li>
<li><tt>is_member_pointer</tt> mistakenly answers <tt>true</tt> for static members.</li>
<li>The <tt>is_convertible</tt> specification is complicated, awkward, and does not work well
with common rvalue reference use cases.</li>
<li>The <tt>is_base_of</tt> trait does not clearly specify what it does with cv-qualified types, or
in the context of multiple inheritance.</li>
<li>The precondition on <tt>is_base_of</tt> is incorrect.</li>
<li><tt>is_signed</tt> and <tt>is_unsigned</tt> do not work for all integral types and enums.</li>
<li>The traits <tt>make_signed</tt> and <tt>make_unsigned</tt> have been found to be useful
in the field, reinvented multiple times, each time a little differently, but are missing from this spec.</li>
<li><tt>rank</tt> does not return 0 for non-array types.</li>
<li><tt>is_empty</tt> is under specified.</li>
<li><tt>has_trivial_construct</tt> has an ambiguous name.  It might refer to
the default constructor, copy constructor, or even both.</li>
<li><tt>has_nothrow_construct</tt> has an ambiguous name.  It might refer to
the default constructor, copy constructor, or even both.</li>
<li>It is not clear how <tt>is_same</tt> works with respect to cv-qualifications.</li>
<li><tt>alignment_of</tt> does not work with arrays of unknown bounds.</li>
<li><tt>aligned_storage</tt> is not usable when the type is not known at
the time the <tt>aligned_storage</tt> is declared.</li>
<li>The use and motivation for the Primary Type Categories and Composite type traits is not
as clear as could be. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#525">LWG issue 525</a></li>
<li><tt>aligned_storage</tt> does not meet any type trait concept.</li>
<li>The definition of all of the <tt>integral_constant</tt>-derived classes is confusing
and inconsistent with the rest of the standard because the derivation is hidden in a remote
section of the WP.</li>
<li>It is unclear which traits react to cv-qualifications and which don't.
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#525">LWG issue 525</a></li>
<li>The definitions of the Secondary classification traits are not clear.  <tt>is_member_pointer</tt>
appears to answer <tt>true</tt> for pointers to static members.</li>
<li>The definition of <tt>is_const</tt> is not sufficiently clear for array types.</li>
<li>Examples for <tt>remove_const</tt> and <tt>remove_cv</tt> are not readable.</li>
<li><tt>remove_reference</tt> does not clearly reflect the existence of rvalue references.</li>
<li>"indirection" is a problem word with Core.</li>
<li><tt>add_pointer</tt> definition is redundant.</li>
<li>Logically related traits do not appear together in the WP, causing confusion.</li>
<li><i>TransformationTrait</i> is misspelled.</li>
</ol>

<p>
Below is a comprehensive proposed fix to all of these problems.
</p>

<p>
The existing organization is:
</p>

<blockquote><pre>
20.4  Metaprogramming and type traits
    20.4.1 Requirements
    20.4.2 Header &lt;type_traits&gt; synopsis
    20.4.3 Helper classes
    20.4.4 General Requirements
    20.4.5 Unary Type Traits
        20.4.5.1 Primary Type Categories
        20.4.5.1 Composite type traits
        20.4.5.3 Type properties
    20.4.6 Relationships between types
    20.4.7 Transformations between types
        20.4.7.1 Const-volatile modifications
        20.4.7.2 Reference modifications
        20.4.7.3 Array modifications
        20.4.7.4 Pointer modifications
    20.4.8 Other transformations
    20.4.9 Implementation requirements
</pre></blockquote>

<p>
This paper proposes a slightly modified organization which groups traits more by
functionality instead of by concepts.  This is a non-normative change motivated
by an attempt to simplify the presentation by putting related traits next to
each other in the standard.
For example this paper puts
all of the array-related traits together, and all of the alignment-related
traits together.  It also eliminates the "other" category as it is not
descriptive of what it contains.
</p>

<blockquote><pre>
20.4  Metaprogramming and type traits
    20.4.1 Requirements
    20.4.2 Header &lt;type_traits&gt; synopsis
    20.4.3 Helper classes
    20.4.4 Type classification traits
        20.4.4.1 Primary classification traits
        20.4.4.2 Secondary classification traits
    20.4.5 Type properties and transformations
        20.4.5.1 Const-volatile properties and transformations
        20.4.5.2 Reference transformations
        20.4.5.3 Pointer transformations
        20.4.5.4 Scalar properties and transformations
        20.4.5.5 Array properties and transformations
        20.4.5.6 Member introspection
        20.4.5.7 Relationships between types
        20.4.5.8 Alignment properties and transformations
</pre></blockquote>

<p>
As can be seen above, the organization of the first three sections has
remained unchanged.  The <tt>Implementation requirements</tt> section
has been dropped as it is no longer desired (this is where the "permission
to get it wrong" was).  The <tt>General Requirements</tt> section has
been dropped because this was essentially just a list of the tables.
However this section did specify which traits met which trait concept.
This information has been moved to the individual sections to which
they apply.  The remaining sections have simply been re-grouped, and
in some cases renamed to something more descriptive.  For example
<tt>Primary Type Categories</tt> became <tt>Primary classification traits</tt>.
</p>

<p>
Additionally this paper proposes reformatting the tabular presentation
into paragraphs as is done in other parts of the standard (e.g. as in
20.5 [function.objects]).  The motivation for this change is to allow more
room for more detailed descriptions of the traits, and accompanying examples
where appropriate.
</p>

<p>
Despite the proposed formatting changes, every effort has been made
to presever the existing wording of the current working paper as much
as possible.  Wording changes are proposed only where:
</p>

<ul>
<li>Normative changes are desired.</li>
<li>Clarifications to the current semantics are required.</li>
<li>Clarified wording offers a significant chance to reduce confusion.</li>
</ul>

<p>
Where parts of a paragraph are changed by this proposal, <ins>insert</ins>/
<del>delete</del> highlighting is used to help clarify what is being changed
and what isn't.
</p>

<blockquote class="note">
Text that appears in this format supplies additional motivation for the
proposed changes.  This format is used so that these motivating statements
are not mistaken for proposed wording.
</blockquote>

<h2><a name="meta"></a>20.4 Metaprogramming and type traits</h2>

<p>
This subclause describes components used by C++ programs, particularly in
templates, to support the widest possible range of types, optimize template code
usage, detect type related user errors, and perform type inference and
transformation at compile time.  <del>It describes type traits requirements,
unary type traits, traits that describe relationships between types, and traits
that perform transformations on types, as summarized in Table 36.</del>
<ins>Included are type classification traits, type property inspection traits,
and type transformations.  The type classification traits describe a complete
taxonomy of all possible C++ types, and state where in that taxonomy a given
type belongs.  The type property inspection traits allow important
characteristics of types, or combinations of types, to be inspected. The type
transformations allow certain properties of types to be manipulated.</ins>
</p>

<blockquote class="note">
The reference to Table 36 has been removed.  The description of the contents
of this section has been reworded in an attempt to be more descriptive.  There
are no normative changes in this section.
</blockquote>

<h3><a name="req"></a>20.4.1 Requirements</h3>

<p>
A <i>UnaryTypeTrait</i> is a <ins>class</ins> template that describes a property of a type. It
shall <del>be a class template that</del> take<del>s</del> one template type argument and, optionally,
additional arguments that help define the property being described. It shall be
<tt>DefaultConstructible</tt><ins>, <tt>CopyConstructible</tt>,</ins> and
<ins>publicly</ins> derived, directly or indirectly, from <del>an instance</del>
<ins>a specialization</ins> of the template
<tt>integral_constant</tt> (20.4.3), with the arguments to the template
<tt>integral_constant</tt> determined by the requirements for the particular
property being described.
</p>

<p>
A <i>BinaryTypeTrait</i> is a <ins>class</ins> template that describes a relationship between two
types. It shall <del>be a class template that</del> take<del>s</del> two template type arguments and,
optionally, additional arguments that help define the relationship being
described. It shall be <tt>DefaultConstructible</tt><ins>,
<tt>CopyConstructible</tt>,</ins> and <ins>publicly</ins> derived, directly or
indirectly, from <del>an instance</del>
<ins>a specialization</ins> of the template <tt>integral_constant</tt>
(20.4.3), with the arguments to the template <tt>integral_constant</tt>
determined by the requirements for the particular relationship being described.
</p>

<p>
A <i>Transformation<del>Type</del>Trait</i> is a template that <del>modifies</del> <ins>adapts</ins> a property
of a type. It shall be a class template that takes one <ins>or more</ins>
template <del>type</del> argument<ins>s</ins> <del>and, optionally, additional
arguments</del> that help define the <del>modification</del> <ins>adaptation</ins>. It shall define a nested type
named <tt>type</tt>, which shall be a synonym for the <del>modified</del> <ins>adapted</ins> type.
</p>

<blockquote class="note">
<p>
The <tt>CopyConstructible</tt> requirement has been added to <i>UnaryTypeTrait</i>
and <i>BinaryTypeTrait</i> as this is key to using these types for tag dispatching.
Also the derivation has been specified to be public which is also important for
tag dispatching.
</p>
<p>
<i>TransformationTrait</i> was inconsistently spelled throughout 20.4 (two different
spellings).  I picked one spelling and considered the other a type-o, corrected
above.  The <i>TransformationTrait</i> concept has also been slightly expanded
such that <tt>aligned_storage</tt> can now be considered to meet this concept.
Without this change <tt>aligned_storage</tt> does not meet any of the three
traits concepts listed above.
</p>
<p>
"Modifies" has been changed to "adapts". The former implies that
something changes, yet nothing changes via these traits.  Instead, a new
type is created that is a variation of an existing type.
</p>

<p>
Rewording generously donated by Jens.
</p>
</blockquote>

<h3><a name="synop"></a>20.4.2 Header <tt>&lt;type_traits&gt;</tt> synopsis</h3>

<blockquote><pre>
namespace std {
  <i>// helper class:</i>
  template &lt;class T, T v&gt; struct integral_constant;
  typedef integral_constant&lt;bool, true&gt;  true_type;
  typedef integral_constant&lt;bool, false&gt; false_type;

  <i>// Primary classification traits:</i>
  template &lt;class T&gt; struct is_void;
  template &lt;class T&gt; struct is_integral;
  template &lt;class T&gt; struct is_floating_point;
  template &lt;class T&gt; struct is_array;
  template &lt;class T&gt; struct is_pointer;
  template &lt;class T&gt; struct is_reference;
  template &lt;class T&gt; struct is_member_object_pointer;
  template &lt;class T&gt; struct is_member_function_pointer;
  template &lt;class T&gt; struct is_enum;
  template &lt;class T&gt; struct is_union;
  template &lt;class T&gt; struct is_class;
  template &lt;class T&gt; struct is_function;

  <i>// Secondary classification traits:</i>
  template &lt;class T&gt; struct is_arithmetic;
  template &lt;class T&gt; struct is_fundamental;
  template &lt;class T&gt; struct is_member_pointer;
  template &lt;class T&gt; struct is_scalar;
  template &lt;class T&gt; struct is_object;
  template &lt;class T&gt; struct is_compound;

  <i>// Const-volatile properties and transformations:</i>
  template &lt;class T&gt; struct is_const;
  template &lt;class T&gt; struct is_volatile;
  template &lt;class T&gt; struct remove_const;
  template &lt;class T&gt; struct remove_volatile;
  template &lt;class T&gt; struct remove_cv;
  template &lt;class T&gt; struct add_const;
  template &lt;class T&gt; struct add_volatile;
  template &lt;class T&gt; struct add_cv;

  <i>// Reference transformations:</i>
  template &lt;class T&gt; struct remove_reference;
  template &lt;class T&gt; struct add_reference;

  <i>// Pointer transformations:</i>
  template &lt;class T&gt; struct remove_pointer;
  template &lt;class T&gt; struct add_pointer;

  <i>// Scalar properties and transformations:</i>
  template &lt;class T&gt; struct is_signed;
  template &lt;class T&gt; struct is_unsigned;

  <i>// Array properties and transformations:</i>
  template &lt;class T&gt; struct rank;
  template &lt;class T, unsigned I = 0&gt; struct extent;
  template &lt;class T&gt; struct remove_extent;
  template &lt;class T&gt; struct remove_all_extents;

  <i>// Member introspection:</i>
  template &lt;class T&gt; struct is_pod;
  template &lt;class T&gt; struct is_empty;
  template &lt;class T&gt; struct is_polymorphic;
  template &lt;class T&gt; struct is_abstract;
  template &lt;class T&gt; struct <ins>has_trivial_default</ins> <del>has_trivial_constructor</del>;
  template &lt;class T&gt; struct has_trivial_copy;
  template &lt;class T&gt; struct has_trivial_assign;
  template &lt;class T&gt; struct has_trivial_destructor;
  template &lt;class T&gt; struct <ins>has_nothrow_default</ins> <del>has_nothrow_constructor</del>;
  template &lt;class T&gt; struct has_nothrow_copy;
  template &lt;class T&gt; struct has_nothrow_assign;
  template &lt;class T&gt; struct has_virtual_destructor;

  <i>// Relationships between types:</i>
  template &lt;class T, class U&gt; struct is_same;
  template &lt;class Base, class Derived&gt; struct is_base_of;
  template &lt;class From, class To&gt; struct is_convertible;

  <i>// Alignment properties and transformations:</i>
  template &lt;class T&gt; struct alignment_of;
  template &lt;size_t Len, size_t Align = <i>most_stringent_alignment_requirement</i>&gt;
    struct aligned_storage;

}  <i>// namespace std</i>
</pre></blockquote>

<p>
The behavior of a program that adds specializations for any of the class
templates defined in this clause is undefined.
</p>

<blockquote class="note">
<p>
The synopsis has simply been reordered and re-commented to reflect
the proposed organization.  The proposed changes for the <tt>has_trivial/nothrow_*</tt>
traits are highlighted here.  It is important that the names of these traits
work well as a group (relative to the names of all similar traits).  The synopsis
is a good place to see all of the names at once, making it easier to decide what
names might be more appropriate.
</p>
<p>
It is feared that using <tt>constructor</tt> in the name results in an
ambiguous name.  Does <tt>constructor</tt> refer to the default constructor
or to the copy constructor, or possibly even both?  Using <tt>default</tt>
instead of <tt>constructor</tt> appears to disambiguate the meaning.
</p>
<p>
The sentence under the synopsis is taken from the current wording verbatim,
but moved.  In the current WP wording this sentence appears in two places:
<tt>Primary Type Categories</tt> and <tt>Composite type traits</tt>.  It
has been moved here to apply to all of the type traits.  Clients should
not specialize any trait in the type traits library.  For TR1 it was
appropriate to allow the client to specialize some traits only because
there was a lack of compiler support for those traits.  Client specialization
was the only workaround.
</p>
</blockquote>

<h3><a name="help"></a>20.4.3 Helper classes</h3>

<blockquote class="note">
No changes.
</blockquote>


<h3><a name="class"></a>20.4.4 Type classification traits</h3>

<p><ins>
The classification traits describe the C++ taxonomy of types.  These traits are
grouped into two broad categories:  primary and secondary.  The primary traits
identify the leaves of the taxonomy tree.  Every type that can be created in C++
fits into one and only one of the primary categories.  The secondary classifications
represent combinations of the primary classifications that are useful for determining
characteristics of a relatively broad range of types (e.g. is a type a scalar?).
</ins></p>

<p><ins>
All traits in this section satisfy the <i>UnaryTypeTrait</i> requirements.
</ins></p>

<blockquote class="note">
<p>
The discussion of the purpose of these traits has been changed to match the
organization.  These traits classify types as opposed to get properties of
types.  The sentence in the WP referring to the implicit instantiation of a
client-supplied type has been moved from this section to 20.4.5 <tt>Type
properties and transformations</tt> as it no longer applies to any trait in this
section.
</p>
<p>
Also a note was added (or moved from the deleted <tt>General Requirements</tt>
section) that these traits fit the <i>UnaryTypeTrait</i> concept.
</p>
</blockquote>

<h4><a name="prim"></a>20.4.4.1 Primary classification traits</h4>

<blockquote><pre>
template &lt;class T&gt; struct is_void : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is <ins>a <tt><i>cv</i></tt></ins>
<tt>void</tt> <ins>type then <tt><i>b</i></tt> is <tt>true</tt>, else it
is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_integral : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is a<del>n</del> <ins><tt><i>cv</i></tt></ins>
integral type ([basic.fundamental]) <ins>then <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_floating_point : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is a <ins><tt><i>cv</i></tt></ins>
floating point type ([basic.fundamental]) <ins>then <tt><i>b</i></tt> is <tt>true</tt>, else
it is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_array : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is an array type ([basic.compound]) <ins>of
known or unknown extent then <tt><i>b</i></tt> is <tt>true</tt>, else it
is <tt>false</tt>.</ins> <ins>[<i>Note:</ins> Class template <tt>array</tt> ([23.2.1])
is <i>not</i> an array type. <ins><i>-- end note</i>]</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_pointer : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is a <ins><tt><i>cv</i></tt></ins>
pointer type ([basic.compound]) <ins>then <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>. [<i>Note:</i> Pointer types
</ins><del>I</del><ins>i</ins>nclude<del>s</del> <del>function
pointers</del> <ins>pointers to functions</ins>, but not pointers to
<ins>non-static</ins> members. <ins><i>-- end note</i>]</ins>
</p>

<blockquote><pre>
<ins>template &lt;class T&gt; struct is_lvalue_reference : public integral_constant&lt;bool, <i>b</i>&gt; {};</ins>
</pre></blockquote>

<p>
<ins>If <tt>T</tt> is an lvalue reference type ([dcl.ref]) then <tt><i>b</i></tt> is <tt>true</tt>, else
it is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
<ins>template &lt;class T&gt; struct is_rvalue_reference : public integral_constant&lt;bool, <i>b</i>&gt; {};</ins>
</pre></blockquote>

<p>
<ins>If <tt>T</tt> is an rvalue reference type ([dcl.ref]) then <tt><i>b</i></tt> is <tt>true</tt>, else
it is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_member_object_pointer : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is a <ins><tt><i>cv</i></tt></ins>
pointer to <ins>non-static</ins> data member <ins>([basic.compound]) then <tt><i>b</i></tt>
is <tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_member_function_pointer : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is a <ins><tt><i>cv</i></tt></ins>
pointer to <ins>non-static</ins> member function <ins>([basic.compound]) then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_enum : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is a<del>n</del> <ins><tt><i>cv</i></tt></ins>
enumeration type ([basic.compound]) <ins>then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_union : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is a <ins><tt><i>cv</i></tt></ins>
union type ([basic.compound]) <ins>then <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_class : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is a <ins><tt><i>cv</i></tt></ins>
class type, <del>but</del> <ins>and</ins> not a union type
([basic.compound]) <ins>then <tt><i>b</i></tt> is <tt>true</tt>, else it
is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_function : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is a function type
([basic.compound]) <ins>then <tt><i>b</i></tt> is <tt>true</tt>, else it
is <tt>false</tt>. [<i>Note:</i> Pointer to (non-member) function types are
pointers, not functions, and references to functions are references, not
functions. <i>-- end note</i>]</ins>
</p>

<blockquote class="note">
<p>
Each trait is individually specified to publicly derive from
<tt>integral_constant&lt;bool, <i>b</i>&gt;</tt>.  This is a
non-normative change from the WP.  Everywhere else in the standard we
consistently show the base class for each individual definition (e.g.
see 20.5.6 [arithmetic.operations]).
</p>
<p>
Words have also been inserted for each trait concerning the effects of
cv-qualifiers.  This is also a non-normative change from the WP.  It is
felt that including this information directly in the definition of each
trait it applies to is less error prone than blanket statements since
not all traits in 20.4 behave this way.  It can become confusing to the
uninitiated which traits ignore cv-qualifiers and which don't.
</p>

<p>
<tt>is_pointer</tt> clarified to answer true for pointers to static members.
This is a normative change.
</p>

<p>
<tt>is_member_object_pointer</tt> changed to answer false for pointers to static members.
This is a normative change.
</p>

<p>
<tt>is_member_function_pointer</tt> changed to answer false for pointers to static members.
This is a normative change.
</p>

<p>
<tt>is_reference</tt> has been moved to the secondary classification traits section.
<tt>is_lvalue_reference</tt> and <tt>is_rvalue_reference</tt> have been added as
primary classification traits.
This is a normative change.
</p>

</blockquote>

<h4><a name="sec"></a>20.4.4.2 Secondary classification traits</h4>

<blockquote><pre>
template &lt;class T&gt; struct is_reference : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del><tt>T</tt> is a reference type ([basic.fundamental])</del>
<ins><tt><i>b</i></tt> equals <tt>is_lvalue_reference&lt;T&gt;::value ||
is_rvalue_reference&lt;T&gt;::value</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_arithmetic : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del><tt>T</tt> is an arithmetic type ([basic.fundamental])</del>
<ins><tt><i>b</i></tt> equals <tt>is_integral&lt;T&gt;::value || is_floating_point&lt;T&gt;::value</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_fundamental : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del><tt>T</tt> is an fundamental type ([basic.fundamental])</del>
<ins><tt><i>b</i></tt> equals <tt>is_void&lt;T&gt;::value || is_arithmetic&lt;T&gt;::value</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_member_pointer : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del><tt>T</tt>  is a pointer to a member or member function</del>
<ins><tt><i>b</i></tt> equals <tt>is_member_object_pointer&lt;T&gt;::value ||
is_member_function_pointer&lt;T&gt;::value</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_scalar : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del><tt>T</tt>  is a scalar type ([basic.types])</del>
<ins><tt><i>b</i></tt> equals
<tt>is_arithmetic&lt;T&gt;::value     ||
    is_member_pointer&lt;T&gt;::value ||
    is_pointer&lt;T&gt;::value        ||
    is_enum&lt;T&gt;::value</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_object : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del><tt>T</tt>  is an object type ([basic.types])</del>
<ins><tt><i>b</i></tt> equals
<tt>is_scalar&lt;T&gt;::value  ||
    is_array&lt;T&gt;::value   ||
    is_union&lt;T&gt;::value   ||
    is_class&lt;T&gt;::value</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_compound : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del><tt>T</tt> is a compound type ([basic.compound])</del>
<ins><tt><i>b</i></tt> equals <tt>!is_fundamental&lt;T&gt;::value</tt>.</ins>
</p>

<blockquote class="note">
<p>
<tt>is_reference</tt> has been moved from the <tt>Primary classification traits</tt>
to here, and had its definition modified appropriately.
</p>
<p>
The main change in this section is to specify the definition of each trait in terms
of the primary traits.  This is intended to be a non-normative change from the WP.
The reason this specification is better is because it leaves no doubt what the intended
definitions are, or how they react with cv-qualified types.  These definitions are 
simpler, more concise, and less prone to be misinterpreted than the definitions in
the current WP.
</p>
<p>
The change for <tt>is_member_pointer</tt> is normative.  The current WP definition includes
pointers to static members.
</p>

</blockquote>

<h3><a name="prop"></a>20.4.5 Type properties and transformations</h3>

<p>
<ins>These traits allow inspection of certain properties of types, and in some cases computing a type
based on the template parameter input.</ins>
</p>

<p>
For all of the class templates <tt>X</tt> declared in this clause, instantiating
that template with a template<del>-</del><ins> </ins>argument that is a class template specialization
may result in the implicit instantiation of the template argument if and only if
the semantics of <tt>X</tt> require that the argument must be a complete type.
</p>

<blockquote class="note">
<p>
The second sentence above (regarding implicit instantiation) has been moved
from 20.4.5 to here as it applies only to traits in this section.
</p>
</blockquote>

<h4><a name="cv"></a>20.4.5.1 Const-volatile properties and transformations</h4>

<p>
<ins>Those traits whose name begins with <tt>is_</tt> satisfy the <i>UnaryTypeTrait</i> requirements.
The remaining traits in this section satisfy the <i>TransformationTrait</i> requirements.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_const : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is const-qualified ([basic.qualifier])
<ins>then <tt><i>b</i></tt> is <tt>true</tt>, else it is
<tt>false</tt>.</ins>
</p>

<p>
<ins>[<i>Example:</i></ins>
</p>

<blockquote><pre><ins>
is_const&lt;const volatile int&gt;::value  // true
is_const&lt;const int*&gt;::value          // false
is_const&lt;const int&amp;&gt;::value          // false
is_const&lt;int[3]&gt;::value              // false
is_const&lt;const int[3]&gt;::value        // true
</ins></pre></blockquote>

<p>
<ins><i>-- end example</i>]</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_volatile : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is volatile-qualified ([basic.qualifier])
<ins>then <tt><i>b</i></tt> is <tt>true</tt>, else it is
<tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct remove_const {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
The member typedef <tt>type</tt> shall be the same <ins>type</ins> as
<tt>T</tt> except that any top<ins>-</ins>level const<del>-</del><ins> </ins>qualifier has been removed.
</p>

<p>
[<i>Example:</i>
</p>

<blockquote><pre>
remove_const&lt;const volatile int&gt;::type  // volatile int
remove_const&lt;const int* const&gt;::type    // const int*
<ins>remove_const&lt;const int&amp;&gt;::type          // const int&amp;
remove_const&lt;const int[3]&gt;::type        // int[3]</ins>
</pre></blockquote>

<p>
<i>-- end example</i>]
</p>

<blockquote><pre>
template &lt;class T&gt; struct remove_volatile {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
The member typedef <tt>type</tt> shall be the same <ins>type</ins> as
<tt>T</tt> except that any top<ins>-</ins>level volatile<del>-</del><ins>
</ins>qualifier has been removed. <del>[<i>Example:</i>
<tt>remove_volatile&lt;const volatile int&gt;::type</tt> evaluates to
<tt>const int</tt>, whereas <tt>remove_volatile&lt;volatile
int*&gt;</tt> is <tt>volatile int*</tt>.  end example ]</del>
</p>

<blockquote><pre>
template &lt;class T&gt; struct remove_cv {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
The member typedef <tt>type</tt> shall <del>be the same as
<tt>T</tt> except that any top-level cv-qualifier has been removed.</del>
<ins>designate the cv-unqualified version of <tt>T</tt>.</ins>
</p>

<p>
[<i>Example:</i>
</p>

<blockquote><pre>
remove_cv&lt;const volatile int&gt;::type      // int
remove_cv&lt;volatile int* volatile&gt;::type  // volatile int*
<ins>remove_cv&lt;const int&amp;&gt;::type              // const int&amp;</ins>
</pre></blockquote>

<p>
<i>-- end example</i>]
</p>

<blockquote><pre>
template &lt;class T&gt; struct add_const {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
If <tt>T</tt> is a reference, function, or top<ins>-</ins>level
const<del>-</del><ins> </ins>qualified type, then <tt>type</tt> shall be
the same type as <tt>T</tt>, otherwise <ins><tt>type</tt> shall be the
same type as</ins> <tt>T const</tt>.
</p>

<blockquote><pre>
template &lt;class T&gt; struct add_volatile {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
If <tt>T</tt> is a reference, function, or top<ins>-</ins>level
volatile<del>-</del><ins> </ins>qualified type, then <tt>type</tt> shall
be the same type as <tt>T</tt>, otherwise <ins><tt>type</tt> shall be
the same type as</ins> <tt>T volatile</tt>.
</p>

<blockquote><pre>
template &lt;class T&gt; struct add_cv {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
The member typedef <tt>type</tt> shall be the same type as
<tt>add_const&lt;typename add_volatile&lt;T&gt;::type&gt;::type</tt>.
</p>

<blockquote class="note">
<p>
All of the traits regarding inspection and manipulation of cv-qualifiers can
be found in this section.  This is a non-normative reorganization from the WP where
these traits were in sections 20.4.5.3 and 20.4.7.1.  It is believed that grouping
these traits together in the same section will be clearer to the reader.
</p>
<p>
Examples have been added to <tt>is_const</tt> which clarify what has proven
to be a confusing point (regarding treatment of arrays).
</p>

<p>
Jens provided new wording for <tt>remove_cv</tt>.
</p>

<p>
The examples for <tt>remove_const</tt> and <tt>remove_cv</tt> have been
included from the WP, and added to, and are far more readable out of the tabular format
as shown herein.  I added one extra example to <tt>remove_const</tt> to
clarify arrays.  I removed the examples from <tt>remove_volatile</tt> as
they seemed redundant.
</p>

<p>
A hypen has been added to "top-level".
</p>

<p>
Minor word-smithing for <tt>add_const</tt>, and <tt>add_volatile</tt>.  The original is a little
terse.
</p>

<p>
No changes are recommended for <tt>add_cv</tt>.
</p>
</blockquote>

<h4><a name="ref"></a>20.4.5.2 Reference transformations</h4>

<p>
<ins>The traits in this section satisfy the <i>TransformationTrait</i> requirements.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct remove_reference {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
<del>The member typedef <tt>type</tt> shall be the same type as <tt>T</tt>,
except that any reference qualifier has been removed.</del>
<ins>If <tt>T</tt> has type "reference to <tt>T1</tt>", then the member
typedef shall designate <tt>T1</tt>, otherwise it shall designate <tt>T</tt>.</ins>
</p>

<blockquote><pre>
<del>template &lt;class T&gt; struct add_reference {typedef <i>implementation</i> type;};</del>
</pre></blockquote>

<p>
<del>If <tt>T</tt> is a reference type, then the member typedef
<tt>type</tt> shall be <tt>T</tt>, otherwise <tt>T&amp;</tt>.</del>
</p>

<blockquote><pre>
template &lt;class T&gt; struct add_lvalue_reference {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
For object and function types <tt>type</tt> shall be the same
type as <tt>T&amp;</tt>.  For rvalue reference types (e.g.
<tt>T&amp;&amp;</tt>), type shall become the corresponding lvalue reference
type (e.g. <tt>T&amp;</tt>).  Else <tt>type</tt> is <tt>T</tt>.
</p>

<blockquote><pre>
template &lt;class T&gt; struct add_rvalue_reference {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
For object and function types <tt>type</tt> shall be the same
type as <tt>T&amp;&amp;</tt>.  Else <tt>type</tt> is <tt>T</tt>.
</p>

<blockquote class="note">
<p>
Jens provided wording for <tt>remove_reference</tt>.
</p>
<p>
<tt>add_reference</tt> has been removed and replaced with <tt>add_lvalue_reference</tt>
and <tt>add_rvalue_reference</tt>.  The definition of these two have been altered (from
the WP's <tt>add_reference</tt>) so that using them with <tt>void</tt> types is well
defined.  This is important as use with <tt>void</tt> types is one of the main
motivating use cases of these traits.  Allowing for <tt>void</tt> is also consistent
with the reference implementation in boost.
</p>
</blockquote>

<h4><a name="ptr"></a>20.4.5.3 Pointer transformations</h4>

<p>
<ins>The traits in this section satisfy the <i>TransformationTrait</i> requirements.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct remove_pointer {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
<del>The member typedef type shall be the same as <tt>T</tt>, except any
top level indirection has been removed.</del> <ins>If <tt>T</tt> is a
<tt><i>cv</i></tt> <tt>pointer</tt> type <tt>A*</tt>, the
member typedef <tt>type</tt> shall be the same as the pointed to type
<tt>A</tt>. Otherwise <tt>type</tt> is the same type as
<tt>T</tt>.</ins>  [<i>Note:</i> pointers to members are left unchanged
by <tt>remove_pointer</tt>.]
</p>

<blockquote><pre>
template &lt;class T&gt; struct add_pointer {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
The member typedef <tt>type</tt> shall be the same type as
<tt>remove_reference&lt;T&gt;::type*</tt><del>, if <tt>T</tt> is a
reference type, otherwise <tt>T*</tt></del>.
</p>

<blockquote class="note">
<p>
The definition of <tt>remove_pointer</tt> has been reworded to avoid the term
"indirection".  This is consistent with core issue 342.
</p>
<p>
The definition of <tt>add_pointer</tt> has been truncated.  In the current WP,
everything from "if" on is redundant.
</p>
</blockquote>

<h4><a name="int"></a>20.4.5.4 Scalar properties and transformations</h4>

<p>
<ins>The traits <tt>is_signed</tt> and <tt>is_unsigned</tt> satisfy the <i>UnaryTypeTrait</i> requirements.
The traits <tt>make_signed</tt> and <tt>make_unsigned</tt> satisfy the <i>TransformationTrait</i> requirements.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_signed : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del><tt>T</tt> is a signed integral type ([basic.fundamental])</del>
<ins>If <tt>is_arithmetic&lt;T&gt;::value</tt> or <tt>is_enum&lt;T&gt;::value</tt> is
<tt>true</tt>, and if <tt>T(-1) &lt; T(0)</tt> then <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_unsigned : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del><tt>T</tt> is an unsigned integral type ([basic.fundamental])</del>
<ins>If <tt>is_arithmetic&lt;T&gt;::value</tt> or <tt>is_enum&lt;T&gt;::value</tt> is
<tt>true</tt>, and if <tt>T(-1) &gt; T(0)</tt> then <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
<ins>template &lt;class T&gt; struct make_signed {typedef <i>implementation</i> type;};</ins>
</pre></blockquote>

<p>
<ins>The member typedef <tt>type</tt> shall be a signed integral type
with the same cv-qualification as <tt>T</tt>.  When <tt>T</tt> is a
signed integral type, the member typedef <tt>type</tt> shall be the same
type as <tt>T</tt>.  When <tt>T</tt> is an unsigned integral type, the
member typedef <tt>type</tt> shall be the corresponding signed integral
type. Otherwise the member typedef <tt>type</tt> shall be the signed
integer type with smallest rank (4.13 [conv.rank]) for which
<tt>sizeof(T) == sizeof(type)</tt>.</ins>
</p>

<p>
<ins><i>Requires:</i> <tt>T</tt> is a <tt><i>cv</i></tt> integral type
or enumeration, but not a <tt>bool</tt> type.</ins>
</p>

<blockquote><pre>
<ins>template &lt;class T&gt; struct make_unsigned {typedef <i>implementation</i> type;};</ins>
</pre></blockquote>

<p>
<ins>The member typedef <tt>type</tt> shall be an unsigned integral type
with the same cv-qualification as <tt>T</tt>.  When <tt>T</tt> is an
unsigned integral type, the member typedef <tt>type</tt> shall be the
same type as <tt>T</tt>.  When <tt>T</tt> is a signed integral type, the
member typedef <tt>type</tt> shall be the corresponding unsigned
integral type.  Otherwise the member typedef <tt>type</tt> shall be the unsigned
integer type with smallest rank (4.13 [conv.rank]) for which
<tt>sizeof(T) == sizeof(type)</tt>.</ins>
</p>

<p>
<ins><i>Requires:</i> <tt>T</tt> is a <tt><i>cv</i></tt> integral type
or enumeration, but not a <tt>bool</tt> type.</ins>
</p>

<blockquote class="note">
<p>
The definition of <tt>is_signed</tt> and <tt>is_unsigned</tt> have been clarified to work with
all integral types (including <tt>char</tt>, <tt>bool</tt>, etc.).  This much is
a clarification of intent from the WP.  Furthermore a suggested change in semantics
is to have these traits work for enums as well.  Note that this definition leaves
no question as to how these traits will react to cv-qualified types.  The current
definition in the WP is not clear on this matter (possibly a normative change,
I'm not sure, but it is what is desired).
</p>
<p>
Additionally floating point types have been declared to work with these traits.  The
motivation is for consistency with <tt>numeric_traits</tt>.  Invariant:
</p>
<blockquote><pre>
std::is_signed&lt;T&gt;::value == std::numeric_limits&lt;T&gt;::is_signed
</pre></blockquote>
<p>
for all arithmetic <tt>T</tt>.
</p>
<p>
Two new traits have been added: <tt>make_signed</tt> and <tt>make_unsigned</tt>.
These traits have been found to be useful in practice and reinvented multiple times.
The multiple implementations in the field tend to have different behaviors in the
corner cases.  This specification standardizes these traits, even for the corner
cases.
</p>
<p>
Invariants for <tt>make_signed</tt> and <tt>make_unsigned</tt>:
</p>
<blockquote>
<p>
Let <tt>S</tt> be <tt>make_signed&lt;T&gt;::type</tt> and <tt>U</tt> be <tt>make_unsigned&lt;T&gt;::type</tt>.
</p>
<ul>
<li><tt>is_signed&lt;S&gt;::value</tt></li>
<li><tt>is_unsigned&lt;U&gt;::value</tt></li>
<li><tt>sizeof(T) == sizeof(S)</tt></li>
<li><tt>sizeof(T) == sizeof(U)</tt></li>
<li><tt>!is_same&lt;S, U&gt;::value</tt></li>
<li><tt>is_convertible&lt;S, U&gt;::value</tt></li>
<li><tt>is_convertible&lt;U, S&gt;::value</tt></li>
<li><tt>numeric_limits&lt;U&gt;::digits == numeric_limits&lt;S&gt;::digits + 1</tt></li>
<li>If <tt>is_integral&lt;T&gt;::value</tt> and <tt>is_signed&lt;T&gt;::value</tt> then
<ul>
<li> <tt>numeric_limits&lt;T&gt;::digits == numeric_limits&lt;S&gt;::digits</tt>, else</li>
<li> <tt>numeric_limits&lt;T&gt;::digits == numeric_limits&lt;U&gt;::digits</tt>.</li>
</ul>
</ul>
</blockquote>

</blockquote>

<h4><a name="arr"></a>20.4.5.5 Array properties and transformations</h4>

<p>
<ins>The traits <tt>rank</tt> and <tt>extent</tt> satisfy the <i>UnaryTypeTrait</i> requirements.
The traits <tt>remove_extent</tt> and <tt>remove_all_extents</tt> satisfy the
<i>TransformationTrait</i> requirements.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct rank : public integral_constant&lt;size_t, <i>v</i>&gt; {};
</pre></blockquote>

<p>
<del>An integer value representing the rank of objects of type
<tt>T</tt> ([dcl.array]). [<i>Note:</i> The term "rank" here is used to
describe the number of dimensions of an array type. <i>-- end note</i>]</del>
<ins><tt><i>v</i></tt> is the number of dimensions of the type <tt>T</tt>.  For types
<tt>T</tt> which are not array types <tt><i>v</i></tt> is <tt>0</tt>.</ins>
</p>

<p>
[<i>Example:</i>
</p>

<blockquote><pre>
// the following assertions hold: 
static_assert(rank&lt;int&gt;::value == 0, ""); 
static_assert(rank&lt;int[2]&gt;::value == 1, ""); 
static_assert(rank&lt;int[][4]&gt;::value == 2, ""); 
</pre></blockquote>

<p>
<i>-- end example</i>]
</p>

<blockquote><pre>
template &lt;class T, unsigned I = 0&gt; struct extent : public integral_constant&lt;size_t, <i>v</i>&gt; {};
</pre></blockquote>

<p>
<del>An integer value representing the extent (dimension) of the
I'th bound of objects of type <tt>T</tt> (8.3.4).</del>
<ins><tt><i>v</i></tt> is the size of the <tt>I</tt>'th dimension of the
type <tt>T</tt>.</ins> If the type <tt>T</tt> is not an array type, has
rank of less than <tt>I</tt>, or if <tt>I == 0</tt> and <tt>T</tt> is of
type "array of unknown <del>bound</del> <ins>extent</ins> of U," then
<del><tt>value</tt></del> <ins><tt><i>v</i></tt></ins> shall
<del>evaluate to</del> <ins>be</ins> zero<ins>.</ins><del>; otherwise
<tt>value</tt> shall evaluate to the number of elements in the
<tt>I</tt>'th array bound of <tt>T</tt>.</del>
</p>
<p>
[<i>Note:</i> The term "extent" here is used to describe the number 
of elements in an array type <i>-- end note</i>]
</p>

<p>
[<i>Example:</i>
</p>

<blockquote><pre>
// the following assertions hold: 
static_assert(extent&lt;int&gt;::value == 0, ""); 
static_assert(extent&lt;int[2]&gt;::value == 2, ""); 
static_assert(extent&lt;int[2][4]&gt;::value == 2, ""); 
static_assert(extent&lt;int[][4]&gt;::value == 0, ""); 
static_assert((extent&lt;int, 1&gt;::value) == 0, ""); 
static_assert((extent&lt;int[2], 1&gt;::value) == 0, ""); 
static_assert((extent&lt;int[2][4], 1&gt;::value) == 4, ""); 
static_assert((extent&lt;int[][4], 1&gt;::value) == 4, ""); 
</pre></blockquote>

<p>
<i>-- end example</i>]
</p>

<blockquote><pre>
template &lt;class T&gt; struct remove_extent {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
If <tt>T</tt> is <ins>a type</ins> "array of <tt>U</tt>", the member typedef <tt>type</tt>
shall be <tt>U</tt>, otherwise <tt>T</tt>. <ins>[<i>Note:</i></ins> For multidimensional arrays,
only the first array dimension is removed. For a
type "array of <tt>const U</tt>", the resulting type is <tt>const
U</tt>. <ins><i>--end note</i>]</ins>
</p>

<p>
[<i>Example:</i>
</p>

<blockquote><pre>
// the following assertions hold: 
static_assert((is_same&lt;remove_extent&lt;int&gt;::type, int&gt;::value), ""); 
static_assert((is_same&lt;remove_extent&lt;int[2]&gt;::type, int&gt;::value), ""); 
static_assert((is_same&lt;remove_extent&lt;int[2][3]&gt;::type, int[3]&gt;::value), ""); 
static_assert((is_same&lt;remove_extent&lt;int[][3]&gt;::type, int[3]&gt;::value), "");
</pre></blockquote>

<p>
<i>-- end example</i>]
</p>

<blockquote><pre>
template &lt;class T&gt; struct remove_all_extents {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
If <tt>T</tt> is "multi-dimensional array of <tt>U</tt>", the member <tt>type</tt> shall be
<tt>U</tt>, otherwise <tt>T</tt>.
</p>

<p>
[<i>Example:</i>
</p>

<blockquote><pre>
// the following assertions hold: 
static_assert((is_same&lt;remove_all_extents&lt;int&gt;::type, int&gt;::value), ""); 
static_assert((is_same&lt;remove_all_extents&lt;int[2]&gt;::type, int&gt;::value), ""); 
static_assert((is_same&lt;remove_all_extents&lt;int[2][3]&gt;::type, int&gt;::value), ""); 
static_assert((is_same&lt;remove_all_extents&lt;int[][3]&gt;::type, int&gt;::value), ""); 
</pre></blockquote>

<p>
<i>-- end example</i>]
</p>

<blockquote class="note">
<p>
All of the traits regarding arrays (except for <tt>is_array</tt> which is a
primary classification trait) can be found in this section. This is a
non-normative reorganization from the WP where these traits were in sections
20.4.5.3 and 20.4.7.3. It is believed that grouping these traits together in the
same section will be clearer to the reader.
</p>
<p>
<tt>rank</tt> of non-array types is specified to be 0 (this is missing
from the WP, a normative change). The examples from the WP are preserved
here but now fall closer to the definition of <tt>rank</tt> due to the
non-table formatting.
</p>
<p>
The wording of the definition of <tt>extent</tt> has been edited for clarity, but
there are no normative changes.  The examples have been preserved.  Note that in the
current WP the reader has to scroll back 4 pages to discover what the base class
of <tt>rank</tt> and <tt>extent</tt> are.
</p>

<p>
Jens provided wording for <tt>remove_extent</tt>.
</p>

<p>
There are no changes at all for <tt>remove_all_extents</tt>.
</p>
</blockquote>

<h4><a name="intr"></a>20.4.5.6 Member introspection</h4>

<p>
<ins>The traits in this section satisfy the <i>UnaryTypeTrait</i> requirements.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_pod : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is a <ins><tt><i>cv</i></tt></ins>
POD type ([basic.types]) <ins>then <tt><i>b</i></tt> is <tt>true</tt>,
else it is <tt>false</tt>.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type</ins>.
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_empty : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del><tt>T</tt> is an empty class ([class])</del>
<ins>If <tt>is_class&lt;T&gt;::value</tt> is <tt>false</tt> then <tt><i>b</i></tt> is
<tt>false</tt>.  Otherwise <tt>T</tt> is considered empty if and only if:</ins>
</p>
<ul>
<li><ins><tt>T</tt> has no non-static data members, or all non-static data members, if any, are
bit-fields of length 0, and</ins></li>
<li><ins><tt>T</tt> has no virtual members, and</ins></li>
<li><ins><tt>T</tt> has no virtual base classes, and</ins></li>
<li><ins><tt>T</tt> has no base classes <tt>B</tt> for which <tt>is_empty&lt;B&gt;::value</tt>
is <tt>false</tt>.</ins></li>
</ul>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type</ins>.
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_polymorphic : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is a polymorphic class [class.virtual] <ins>then <tt><i>b</i></tt> is <tt>true</tt>,
else it is <tt>false</tt>.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct is_abstract : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> is an abstract class [class.abstract] <ins>then <tt><i>b</i></tt> is <tt>true</tt>,
else it is <tt>false</tt>.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct has_trivial_<ins>default</ins><del>constructor</del>
    : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del>The default constructor for <tt>T</tt> is trivial ([class.ctor])</del>
<ins>If <tt>is_pod&lt;T&gt;::value</tt> is <tt>true</tt> then <tt><i>b</i></tt> is
<tt>true</tt>, else if <tt>T</tt> is a <tt><i>cv</i></tt> class or
union type (or array thereof) with a trivial default constructor ([class.ctor]) then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct has_trivial_copy : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del>The copy constructor for <tt>T</tt> is trivial ([class.copy])</del>
<ins>If <tt>is_pod&lt;T&gt;::value</tt> or <tt>is_reference&lt;T&gt;::value</tt> is
<tt>true</tt> then <tt><i>b</i></tt> is <tt>true</tt>, else if <tt>T</tt> is a
<tt><i>cv</i></tt> class or union type with a trivial copy
constructor ([class.copy]) then <tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct has_trivial_assign : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del>The assignment operator for <tt>T</tt> is trivial ([class.copy])</del>
<ins>If <tt>is_const&lt;T&gt;::value</tt> or
<tt>is_reference&lt;T&gt;::value</tt> is <tt>true</tt> then
<tt><i>b</i></tt> is <tt>false</tt>. Otherwise if
<tt>is_pod&lt;T&gt;::value</tt> is <tt>true</tt> then <tt><i>b</i></tt>
is <tt>true</tt>, else if <tt>T</tt> is a <tt><i>cv</i></tt>
class or union type with a trivial copy assignment ([class.copy]) then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct has_trivial_destructor : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del>The destructor for <tt>T</tt> is trivial ([class.dtor])</del>
<ins>If <tt>is_pod&lt;T&gt;::value</tt> or <tt>is_reference&lt;T&gt;::value</tt> is
<tt>true</tt> then <tt><i>b</i></tt> is <tt>true</tt>, else if <tt>T</tt> is a
<tt><i>cv</i></tt> class or union type (or array thereof) with a
trivial destructor ([class.dtor]) then <tt><i>b</i></tt> is <tt>true</tt>, else it is
<tt>false</tt>.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct has_nothrow_<ins>default</ins><del>constructor</del>
     : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del>The default constructor for <tt>T</tt> has an empty exception
specification or can otherwise be deduced never to throw an exception</del>
<ins>If <tt>has_trivial_default&lt;T&gt;::value</tt> is <tt>true</tt> then
<tt><i>b</i></tt> is <tt>true</tt>, else if <tt>T</tt> is a <tt><i>cv</i></tt>
class or union type (or array thereof) with a default
constructor that is known not to throw an exception then <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct has_nothrow_copy : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del>The copy constructor for <tt>T</tt> has an empty exception
specification or can otherwise be deduced never to throw an
exception</del>
<ins>If <tt>has_trivial_copy&lt;T&gt;::value</tt> is <tt>true</tt> then
<tt><i>b</i></tt> is <tt>true</tt>, else if <tt>T</tt> is a <tt><i>cv</i></tt>
class or union type with a copy constructor that is
known not to throw an exception then <tt><i>b</i></tt> is <tt>true</tt>, else it
is <tt>false</tt>.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct has_nothrow_assign : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del>The assignment operator for <tt>T</tt> has an empty exception
specification or can otherwise be deduced never to throw an exception
</del>
<ins>If <tt>has_trivial_assign&lt;T&gt;::value</tt> is <tt>true</tt> then
<tt><i>b</i></tt> is <tt>true</tt>, else if <tt>T</tt> is a <tt><i>cv</i></tt>
class or union type with a copy assignment operator (taking an
lvalue of type <tt>T</tt>) that is known not to throw an exception then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>. If <tt>T</tt> is
a <tt>const</tt> type, the copy assignment operator must be both known not to throw
an exception, and <tt>const</tt> qualified, for <tt><i>b</i></tt> to be
<tt>true</tt>.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct has_virtual_destructor : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> <del>has</del> <ins>is a class type with</ins>
a virtual destructor ([class.dtor]) <ins>then <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete type<ins>, an array type of
unknown bounds, or is a <tt>void</tt> type.</ins>
</p>

<blockquote class="note">
<p>
These 12 traits all deal with inspecting certain member functions (or the lack thereof)
in types.  Therefore they have been put in this section titled <tt>Member introspection</tt>.
In the current WP they are all found in 20.4.5.3 <tt>Type properties</tt> along with the
<tt>is_const</tt>, <tt>is_volatile</tt>, <tt>is_signed</tt>, and <tt>is_unsigned</tt> traits.
</p>
<p>
All of the traits in this section have been extended to work with arrays
of unknown bounds, and with <tt>void</tt> types (a normative change). 
This is important for ease in meta-programming.  Otherwise programmers
have to weed out these cases indivdually which is tedious and error
prone.
</p>
<p>
Just in case there is any question, <tt>is_pod</tt> has been clarified to work
with cv-qualified types identically as it would with cv-unqualified types.
</p>
<p>
The <tt>is_empty</tt> specification in the WP is inadequate.  The definition of
an empty class is not well specified in the WP.  The definition proposed herein
attempts to specify exactly what an empty class is.
</p>
<p>
<tt>has_trivial_default</tt> is renamed from <tt>has_trivial_constructor</tt>
and the definition has been changed to explicitly include what happens when given
non-class types (such as <tt>void</tt> or scalars), and cv-qualified types.  Array
types are specifically mentioned in the definition for clarity as well.  This is
considerably better specified than the current WP, and consistent with the use
cases for this trait.  This is arguably a normative change, but I'm not positive.
However I am positive it is a desired change consistent with the reference implementation
at boost.
</p>

<p>
<tt>has_trivial_copy</tt> has been specified to be true for all pod-types and
reference types, as well as cv-qualified class types with trivial copy constructors.
This is important for the use cases this trait is commonly used (optimization by
memcpy for example).  This is likely a normative change.
</p>
<p>
<tt>has_trivial_assign</tt> has been specified to be false for
const qualified types and reference types.  Otherwise true for
pod types.  And then check for trivial assigment operators in class
types.  This is considerably better specified than the current WP, and
consistent with the use cases for this trait.  This is a normative change.
</p>
<p>
<tt>has_trivial_destructor</tt> has been specified to be true for
pod and reference types.  And then check for trivial destructors in class
types (or arrays thereof).  This is considerably better specified than the current WP, and
consistent with the use cases for this trait.  This is a normative change.
</p>
<p>
<tt>has_nothrow_default</tt> has been specified to be true for
pod types.  And then check for nothrow default constructors in class
types (or arrays thereof).  This is considerably better specified than the current WP, and
consistent with the use cases for this trait.  This is a normative change.
</p>
<p>
<tt>has_nothrow_copy</tt> has been specified to be true for all types
for which <tt>has_trivial_copy</tt> is also true.  And then check for
nothrow copy constructors in class types.  This is considerably better
specified than the current WP, and consistent with the use cases for
this trait. This is a normative change.
</p>
<p>
<tt>has_nothrow_assign</tt> has been given a much more detailed specification which results
in normative changes.  For example it can be different in the way it treats <tt>const</tt> types.
</p>
</blockquote>

<h4><a name="rel"></a>20.4.5.7 Relationships between types</h4>

<p>
<ins>The traits in this section satisfy the <i>BinaryTypeTrait</i> requirements.</ins>
</p>

<blockquote><pre>
template &lt;class T, class U&gt; struct is_same : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>T</tt> and <tt>U</tt> <del>name</del> <ins>are</ins>
the same type<ins>, with identical <i>cv</i>-qualifications, then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<blockquote><pre>
template &lt;class Base, class Derived&gt; struct is_base_of : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<ins>If</ins> <tt>Base</tt> is a base class of <tt>Derived</tt>
([class.derived]) <del>or <tt>Base</tt> and <tt>Derived</tt> name the
same type</del> <ins>then <tt><i>b</i></tt> is <tt>true</tt>, otherwise
it is <tt>false</tt>. Top-level cv-qualifiers of <tt>Base</tt> and
<tt>Derived</tt> are ignored. For the purposes of
this trait, a class type (20.4.4.1 [Primary classification traits]) is
considered its own base.</ins>
</p>

<p>
<ins>[<i>Note:</i> <tt>is_base_of</tt> does consider private, protected
and ambiguous base classes as bases. <i>--end note</i>] </ins>
</p>

<p>
<ins>[<i>Example:</i></ins>
</p>
<blockquote><pre><ins>
struct B {};
struct B1 : B {};
struct B2 : B {};
struct D : private B1, private B2 {};

is_base_of&lt;B, D&gt;::value        // true
is_base_of&lt;const B, D&gt;::value  // true
is_base_of&lt;B, const D&gt;::value  // true
is_base_of&lt;B, const B&gt;::value  // true
is_base_of&lt;D, B&gt;::value        // false
is_base_of&lt;B&amp;, D&amp;&gt;::value      // false
is_base_of&lt;B[3], D[3]&gt;::value  // false
is_base_of&lt;int, int&gt;::value    // false
</ins></pre></blockquote>

<p>
<ins>[<i>--end example</i>]</ins>
</p>

<p>
<ins>Requires: If <tt>Base</tt> and <tt>Derived</tt> are class types (20.4.4.1 [Primary classification traits]),
and are not the same type (disregarding cv-qualifiers), <tt>Derived</tt> shall be a complete
type.  A diagnostic is required if this requirement is not met.</ins>
</p>

<blockquote><pre>
template &lt;class From, class To&gt; struct is_convertible : public integral_constant&lt;bool, <i>b</i>&gt; {};
</pre></blockquote>

<p>
<del>An imaginary lvalue of type <tt>From</tt> is implicitly 
convertible to type <tt>To</tt>
([conv])</del>
</p>
<p>
<del>Special conversions involving 
string-literals and null-pointer 
constants are not considered ([conv.array], [conv.ptr], and 
[conv.mem]). No function-parameter 
adjustments ([dcl.fct]) are made to 
type To when determining whether 
From is convertible to To; this 
implies that if type To is a function 
type or an array type, then the 
condition is false. 
See below.
</del>
</p>

<p>
<del>The expression <tt>is_convertible&lt;From,To&gt;::value</tt> is ill-formed if:</del>
</p>

<ul>
<li><del>Type <tt>From</tt> is an incomplete type ([basic.types]).</del></li>
<li><del>Type <tt>To</tt> is an incomplete or abstract type ([basic.types]).</del></li>
<li><del>The conversion is ambiguous. An example of an ambiguous
conversion is a type <tt>From</tt> that has multiple base classes of
type <tt>To</tt> ([class.member.lookup]).</del></li>
<li><del>Type <tt>To</tt> is of class type and the conversion would
invoke a non-public constructor of <tt>To</tt> ([class.access] and
[class.conv.ctor]).</del></li>
<li><del>Type <tt>From</tt> is of class type and the conversion would
invoke a non-public conversion operator of <tt>From</tt> ([class.access]
and [class.conv.fct]).</del></li>
</ul>

<p>
<del>Except that:</del>
</p>

<ul>
<li><del>When <tt>From</tt> is <tt>void</tt> and <tt>To</tt> is not
<tt>void</tt> then value is <tt>false</tt>.</del></li>
<li><del>When <tt>To</tt> is <tt>void</tt> then value is <tt>true</tt>.</del></li>
</ul>

<p>
<ins>If the following <tt>test</tt> function is well formed code <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>.</ins>
</p>

<blockquote><pre><ins>
template &lt;class T&gt; typename add_rvalue_reference&lt;T&gt;::type create();
To test() {return create&lt;From&gt;();}
</ins></pre></blockquote>

<p>
<ins>[<i>Note:</i> This definition gives well defined results for <tt>reference</tt> types,
<tt>void</tt> types, array types and function types.<i>--end note</i>]</ins>
</p>

<p>
<ins>Requires: <tt>From</tt> and <tt>To</tt> are complete types, arrays
of unknown bounds, or <tt>void</tt> types.</ins>
</p>

<blockquote class="note">
<p>
The organization of this section is unchanged from the WP.  It has the same name and contents.  But
it does fall under a different parent section.
</p>
<p>
<tt>is_same</tt> is clarified as to how it works with cv-qualifications.  Some may view this as
a normative change and some may not.  Thus clarification is critical.
</p>

<p>
The changes for <tt>is_base_of</tt> are normative.  This proposal clarifies that it must work
with public, protected and private derivation, as well as with multiple inheritance.  These
words also specify how cv-qualifiers are handled.
</p>

<p>
There are those that would much prefer the name <tt>is_base_and_derived</tt> instead of
<tt>is_base_of</tt>.  And there are those who strongly feel the opposite.  I have no
strong feelings either way.  I am simply noting the issue here.
</p>

<p>
The changes for <tt>is_convertible</tt> are normative.
</p>

<p>
Given a type <tt>T</tt>, the TR1 <tt>is_convertible&lt;T, T&amp;&gt;::value</tt> is <tt>true</tt>
whereas this paper proposes <tt>false</tt> unless <tt>T</tt> is a non-volatile but const qualified
type.  There is good motivation for this change.
</p>

<p>
Consider this code:
</p>

<blockquote><pre>
template &lt;class T&gt;
class container
{
public:
    ...
    template &lt;class U&gt;
    typename where
    &lt;
        is_convertible&lt;U, T&gt;::value,
        iterator
    &gt;::type
    insert(const_iterator position, U&amp;&amp; x);
};
</pre></blockquote>

<p>
The above is not contrived code.  I wrote exactly this code when putting move semantics into
<tt>std::map</tt>.  In that case <tt>T</tt> is a <tt>pair&lt;const key_type, mapped_type&gt;</tt>,
and <tt>U</tt> is some type that must be convertible to the <tt>pair</tt>, most notably a
<tt>pair&lt;key_type, mapped_type&gt;</tt> (without the <tt>const</tt>).  The rationale for
accepting such (non-const) types is so that values can be efficiently moved into the <tt>map</tt>.
</p>

<p>
If an lvalue argument is passed (say of type <tt>P</tt>), <tt>U</tt> gets deduced as a <tt>P&amp;</tt>,
else it gets deduced as <tt>P</tt>.  Subsequently <tt>is_convertible</tt> will be testing
<tt>P&amp;</tt> against <tt>T</tt> if an lvalue argument was passed, or
<tt>P</tt> against <tt>T</tt> if an rvalue was passed --- exactly as needed if <tt>is_convertible</tt>
considers its <tt>From</tt> types to be rvalues!
</p>

<p>
If instead <tt>is_convertible</tt> traffics in lvalue <tt>From</tt> types, then the above
code is wrong because it will consider an rvalue <tt>P</tt> as an lvalue when doing the
<tt>is_convertible</tt> test.  To regain the correct semantics, the following rewrite
will work:
</p>

<blockquote><pre>
template &lt;class T&gt;
class container
{
public:
    ...
    template &lt;class U&gt;
    typename where
    &lt;
        is_convertible&lt;U&amp;&amp;, T&gt;::value,
        iterator
    &gt;::type
    insert(const_iterator position, U&amp;&amp; x);
};
</pre></blockquote>

<p>
Now if an lavlue <tt>P</tt> is passed, <tt>U</tt> is deduced as <tt>P&amp;</tt>
and <tt>is_convertible</tt> will compare a <tt>P&amp; &amp;&amp;</tt> which
collapses to <tt>P&amp;</tt> to <tt>T</tt>.  And if an ravlue <tt>P</tt> is
passed, <tt>U</tt> is deduced as <tt>P</tt> and <tt>is_convertible</tt> will
compare a <tt>P&amp;&amp;</tt> to <tt>T</tt>.
</p>

<p>
So either way can be made to work, but the former seems easier to read, easier to
understand, and less error prone (things just work with the most natural syntax).
That is, you can write the latter and have your code work correctly no matter
what <tt>is_convertible</tt> does with <tt>From</tt> types (rvalue or lvalue).
However if you forget to add the "&&", or if you get confused and can't remember
whether <tt>U&amp;</tt> or <tt>U&amp;&amp;</tt> is correct, just writing <tt>U</tt>
will give you the correct code only if <tt>is_convertible</tt> considers <tt>From</tt>
as an rvalue.
</p>

<p>
The above definition means that casual use of <tt>is_convertible</tt> with
movable but non-copyable types (which can exist in C++03) is more likely to give
an intuitively correct answer.  For example:
</p>
<blockquote><pre>
is_convertible&lt;unique_ptr&lt;Derived&gt;, unique_ptr&lt;Base&gt;&gt;::value;  // true
</pre></blockquote>
<p>
If the client wishes to force the semantics of <tt>From</tt> being considered
an lvalue, it is possible to do so using references:
</p>
<blockquote><pre>
is_convertible&lt;unique_ptr&lt;Derived&gt;&amp;, unique_ptr&lt;Base&gt;&gt;::value;  // false, From is lvalue
</pre></blockquote>
<p>
If <tt>To</tt> is an <tt>array</tt> or <tt>function</tt> type, the result is <tt>false</tt>
since these types are not allowed to be return types.  Note however that these types can
be <tt>From</tt> because of the <tt>add_rvalue_reference</tt> (you can have references to
these types).
</p>

<p>
If <tt>To</tt> and <tt>From</tt> are <tt>void</tt> types, the result is <tt>true</tt>
(no matter the <i>cv</i>-qualifications).  However if only one of <tt>To</tt> or
<tt>From</tt> is a <tt>void</tt> type, then the result is <tt>false</tt>.  Note that this is
another normative change from the WP which specifies that any type is convertible to <tt>void</tt>.
The motivation for this change is that it is not useful in practice.  Note how the TR1 spec had
to make an exception in this area.  For the proposed definition, behavior with <tt>void</tt> types
falls out of the definition with no need for exceptions to the rule.
</p>

<p>
If <tt>From</tt> is an <tt>array</tt> type then it will be convertible to appropriate
<tt>To</tt> pointer types.
</p>

<p>
If <tt>From</tt> is a <tt>function</tt> type then it will be convertible to
appropriate <tt>To</tt> <tt>function pointer</tt> types.  It is not convertible to <tt>function
reference</tt> types because the source is considered an rvalue, and one can not have a reference
to a <tt>const function</tt> type.  <tt>function</tt> types are not covertible to a <tt>function</tt> types
because one can not use <tt>function</tt> types as the return type of a function.
</p>

<p>
Library implementor's note:  Except for the protected/private access checks, and the ambiguity checks,
this specification is completely implementable in C++03 (even without rvalue references).  However
it is intended that this be implemented with compiler help to get the access and ambiguity checks
correct.
</p>
</blockquote>

<h4><a name="algn"></a>20.4.5.8 Alignment properties and transformations</h4>

<p>
<ins>The trait <tt>alignment_of</tt> satisfies the <i>UnaryTypeTrait</i> requirements.
The trait <tt>aligned_storage</tt> satisfies the <i>TransformationTrait</i> requirements.</ins>
</p>

<blockquote><pre>
template &lt;class T&gt; struct alignment_of : public integral_constant&lt;size_t, <i>v</i>&gt; {};
</pre></blockquote>

<p>
<del>An integer value representing</del> <ins><tt><i>v</i></tt> is</ins>
the number of bytes of the alignment of objects of type <tt>T</tt>
<ins>(i.e. the <i>alignment requirement</i> [basic.types])</ins>; an
object of type <tt>T</tt> may be allocated at an address that is a
multiple of its alignment <del>([basic.types])</del>.  <ins>If
<tt>T</tt> is a reference type, <tt>alignment_of</tt> finds the
alignment of the reference, not of the referenced type.  If <tt>T</tt>
is an array type, <tt>alignment_of</tt> finds the alignment of the
array's element type.</ins>
</p>

<p>
Requires: <tt>T</tt> shall be a complete <ins><tt>object</tt></ins> type<ins>, or a <tt>reference</tt>
type, or an array type of unknown bounds</ins>.
</p>

<blockquote><pre>
template &lt;size_t Len, size_t Align <ins>= <i>most_stringent_alignment_requirement</i></ins>&gt;
struct aligned_storage {typedef <i>implementation</i> type;};
</pre></blockquote>

<p>
The member typedef <tt>type</tt> shall be a POD type suitable for use as
uninitialized storage for any object whose size is at most <tt><i>Len</i></tt> and
whose alignment requirement is a divisor of <tt><i>Align</i></tt>.  <ins>If <tt>Align</tt>
is defaulted, it will be a multiple of the most stringent alignment requirement
of any valid C++ object type whose size is no greater than <tt>Len</tt> [expr.new].</ins>
</p>

<p>
Requires: <tt>Len</tt> is nonzero.  <ins>If not defaulted,</ins> <tt>Align</tt> is equal to
<tt>alignment_of&lt;T&gt;::value</tt> for some type <tt>T</tt>.
</p>

<p>
[<i>Note:</i> a typical implementation would define type as:
</p>

<blockquote><pre>
union type
{
  unsigned char __data[Len];
  <i>Aligner</i> __align;
};
</pre></blockquote>

<p>
where <tt><i>Aligner</i></tt> is the smallest POD type for which
<tt>alignment_of&lt;<i>Aligner</i>&gt;::value</tt> is <ins>a multiple of</ins> <tt>Align</tt>.
</p>

<p> <i>-- end note</i>]</p>

<blockquote class="note">
<p>
This section collects the two alignment-related traits into the same section.  In the current
WP they are located in 20.4.5.3 [meta.unary.prop] and 20.4.8 [meta.trans.other].
</p>
<p>
These traits may need to be altered (or eliminated altogether) if/when N2140 gets into the WP.
</p>
<p>
The proposed wording clarifies how <tt>alignment_of</tt> works with reference types, and arrays
of unknown bounds (which are incomplete types).  <tt>alignment_of</tt> is not required to work
with function or <tt>void</tt> types.  Working with arrays of unknown bounds is a normative
change.
</p>
<p>
The defaulted second argument for <tt>aligned_storage</tt> allows one to
create storage for types of unknown alignment requirements (e.g. as
<tt>operator new</tt> does).  The wording "most stringent alignment
requirement" is taken from [expr.new].
</p>
</blockquote>

<h2><a name="ack"></a>Acknowledgments</h2>

<p>
Excellent editing and suggestions by Walter Brown and Robert Klarer are gratefully acknowledged.
</p>

</body>
</html>
