<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: N2028=06-0098<br>
<br>
<a href="mailto:howard.hinnant@gmail.com">Howard E. Hinnant</a><br>

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


<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 Integral properties</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>
This paper proposes a few normative changes to the type traits library.
</p>

<ul>
<li>Permission to "get it wrong" has been removed.</li>
<li>Composite traits have been given precise definitions.</li>
<li><tt>has_trivial_constructor</tt> is renamed to <tt>has_trivial_default</tt>
to disambiguate which constructor is being referred to.</li>
<li><tt>has_nothrow_constructor</tt> is renamed to <tt>has_nothrow_default</tt>
to disambiguate which constructor is being referred to.</li>
<li>Several traits which before required complete types, now also work with
<tt>void</tt> types, and arrays with unknown bounds.</li>
<li><tt>add_reference</tt> now works with <tt>void</tt> types.</li>
<li><tt>is_empty</tt> given a more precise definition.</li>
<li><tt>is_polymorphic</tt> given a more precise definition.</li>
<li><tt>is_signed</tt> and <tt>is_unsigned</tt> clarified for <tt>char</tt>,
<tt>wchar_t</tt> and <tt>bool</tt>.</li>
<li><tt>is_same</tt> clarified with respect to cv-qualifiers.</li>
<li><tt>is_convertible</tt> given a more precise definition which also
gives the client the ability to specify whether the source is an lvalue or rvalue.
This definition also takes access into account.</li>
<li><tt>aligned_storage</tt> given a default value for its second argument.</li>
<li>If rvalue reference is accepted, the subsequent recommended changes to this library
are noted.</li>
</ul>

<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 (for example) puts
all of the array-related traits together, and all of the alignment-related
traits together.  It also eliminates the "other" category.
</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 Integral properties
        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>
Additionally this paper proposes some formatting changes.  More
in depth specifications are more convenient in a paragraph format than a tabular format.
</p>

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

<p>
This sub-clause 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>

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

<p>
A <i>UnaryTypeTrait</i> is a template that describes a property of a type. It
shall be a class template that takes 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
derived, directly or indirectly, from an instance 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 template that describes a relationship between
two types. It shall be a class template that takes two template type arguments
and, optionally, additional arguments that help define the relationship being
described. It shall be DefaultConstructible<ins>,
<tt>CopyConstructible</tt>,</ins> and derived, directly or indirectly, from an
instance 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 modifies 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 modification. It shall define a nested type
named <tt>type</tt>, which shall be a synonym for the modified type.
</p>

<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>// Integral properties:</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>

<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>
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?).
</p>

<p>
All traits in this section model <i>UnaryTypeTrait</i>.
</p>

<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>
If <tt>T</tt> is a (possibly <i>cv</i>-qualified) <tt>void</tt> type then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

<p>
If <tt>T</tt> is a (possibly <i>cv</i>-qualified) integral type then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

<p>
If <tt>T</tt> is a (possibly <i>cv</i>-qualified) floating point type then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

<p>
If <tt>T</tt> is an array type of known or unknown bounds then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

<p>
If <tt>T</tt> is a (possibly <i>cv</i>-qualified) pointer type then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>. Pointer types
include pointers to functions, but not pointers to non-static members.
</p>

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

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

<blockquote class="note">
<p>
If rvalue references are accepted into the language then <tt>is_reference</tt>
will become a secondary classification trait, and will be based on <tt>is_lvalue_reference</tt>
and <tt>is_rvalue_reference</tt> which need to be added:
</p>

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

<p>
If <tt>T</tt> is an lvalue reference type then <tt><i>b</i></tt> is <tt>true</tt>, else
it is <tt>false</tt>.
</p>

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

<p>
If <tt>T</tt> is an rvalue reference type then <tt><i>b</i></tt> is <tt>true</tt>, else
it is <tt>false</tt>.
</p>
</blockquote>

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

<p>
If <tt>T</tt> is a (possibly <i>cv</i>-qualified) pointer to non-static member
data type then <tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</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>
If <tt>T</tt> is a (possibly <i>cv</i>-qualified) pointer to non-static member
function type then <tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

<p>
If <tt>T</tt> is a (possibly <i>cv</i>-qualified) pointer to an enumeration type
then <tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

<p>
If <tt>T</tt> is a (possibly <i>cv</i>-qualified) union type
then <tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

<p>
If <tt>T</tt> is a (possibly <i>cv</i>-qualified) class type, and not a union
type then <tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

<p>
If <tt>T</tt> is a non-member function type then <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>. Note that pointer to function types
are pointers, not functions, and references to functions are references, not
functions.
</p>

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

<blockquote class="note">
<p>
If rvalue references are accepted into the language then <tt>is_reference</tt>
becomes a secondary classification trait:
</p>

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

<p>
<tt><i>b</i></tt> equals <tt>is_lvalue_reference&lt;T&gt;::value || is_rvalue_reference&lt;T&gt;::value</tt>.
</p>
</blockquote>

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

<p>
<tt><i>b</i></tt> equals <tt>is_integral&lt;T&gt;::value || is_floating_point&lt;T&gt;::value</tt>.
</p>

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

<p>
<tt><i>b</i></tt> equals <tt>is_void&lt;T&gt;::value || is_arithmetic&lt;T&gt;::value</tt>.
</p>

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

<p>
<tt><i>b</i></tt> equals <tt>is_member_object_pointer&lt;T&gt;::value ||
is_member_function_pointer&lt;T&gt;::value</tt>.
</p>

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

<p>
<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>.
</p>

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

<p>
<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>.
</p>

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

<p>
<tt><i>b</i></tt> equals <tt>!is_fundamental&lt;T&gt;::value</tt>.
</p>

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

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

<p>
For all of the class templates <tt>X</tt> declared in this clause, instantiating
that template with a template-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>

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

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

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

<p>
If <tt>T</tt> has a top level const qualifier then <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>.
</p>

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

<blockquote><pre>
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
</pre></blockquote>

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

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

<p>
If <tt>T</tt> has a top level volatile qualifier then <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>.
</p>

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

<p>
<tt>type</tt> is the same type as <tt>T</tt> except that any top level
const-qualifier has been removed (if it exists).
</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*
remove_const&lt;const int&amp;&gt;::type          // const int&amp;
</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>
<tt>type</tt> is the same type as <tt>T</tt> except that any top level
volatile-qualifier has been removed (if it exists).
</p>

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

<p>
<tt>type</tt> is the same type as <tt>T</tt> except that all top level
cv-qualifiers have been removed (if they exist).
</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*
remove_cv&lt;const int&amp;&gt;::type              // const int&amp;
</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 level const-qualified type, then
<tt>type</tt> shall be the same type as <tt>T</tt>, otherwise <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 level volatile-qualified type, then
<tt>type</tt> shall be the same type as <tt>T</tt>, otherwise <tt>T volatile</tt>.
</p>

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

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

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

<p>
The traits in this section model <i>TransformationTrait</i>. 
</p>

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

<p>
<tt>type</tt> shall be the same type as <tt>T</tt>, except that any reference
qualifier has been removed.
</p>

<blockquote class="note">
<p>
If the rvalue reference is accepted, the <tt>remove_reference</tt> description
should be changed to:
</p>
<blockquote>
<p>
<tt>type</tt> shall be the same type as <tt>T</tt>, except that any lvalue reference
or rvalue reference qualifier has been removed.
</p>
</blockquote>
</blockquote>

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

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

<blockquote class="note">
<p>
If the rvalue reference is accepted, <tt>add_reference</tt> should be removed
and replaced with:
</p>

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

<p>
For <tt>object</tt> and <tt>function</tt> 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 <tt>object</tt> and <tt>function</tt> 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>

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

<p>
The traits in this section model <i>TransformationTrait</i>. 
</p>

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

<p>
If <tt>T</tt> is a (possibly <i>cv</i>-qualified) <tt>pointer</tt> type <tt>A*</tt>,
<tt>type</tt> becomes the pointed to type <tt>A</tt>, Otherwise <tt>type</tt> is the
same type as <tt>T</tt>.  [<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>
<tt>type</tt> shall be the same type as <tt>remove_reference&lt;T&gt;::type*</tt>.
</p>

<h4><a name="int"></a>20.4.5.4 Integral properties</h4>

<p>
The traits in this section model <i>UnaryTypeTrait</i>. 
</p>

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

<p>
If <tt>is_integral&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>.
</p>

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

<p>
If <tt>is_integral&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>.
</p>

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

<p>
The traits <tt>rank</tt> and <tt>extent</tt> model <i>UnaryTypeTrait</i>.  The
traits <tt>remove_extent</tt> and <tt>remove_all_extents</tt> model
<i>TransformationTrait</i>.
</p>

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

<p>
<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>.
</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>
<tt><i>v</i></tt>
is the size of the <tt>I</tt>'th dimension of the type <tt>T</tt>.  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 bound of U," then <tt><i>v</i></tt> is <tt>0</tt>.
</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 "array of <tt>U</tt>", the member <tt>type</tt> shall be
<tt>U</tt>, otherwise <tt>T</tt>. For multidimensional arrays, only the first
(leftmost) array dimension is removed. For a type "array of <tt>const U</tt>",
the resulting type is <tt>const U</tt>.
</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>

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

<p>
The traits in this section model <i>UnaryTypeTrait</i>. 
</p>

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

<p>
If <tt>T</tt> is a (possibly <i>cv</i>-qualified) <tt>pod</tt>-type then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

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

<p>
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:
</p>
<ul>
<li><tt>T</tt> has no non-static data members, or all non-static data members are
bit-fields of length 0, and</li>
<li><tt>T</tt> has no virtual members, and</li>
<li><tt>T</tt> has no virtual base classes, and</li>
<li><tt>T</tt> has no base classes <tt>B</tt> for which <tt>is_empty&lt;B&gt;::value</tt>
is <tt>false</tt>.</li>
</ul>

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

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

<p>
If <tt>T</tt> has a virtual function then <tt><i>b</i></tt> is <tt>true</tt>,
else it is <tt>false</tt>.
</p>

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

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

<p>
If <tt>T</tt> has a pure virtual function then <tt><i>b</i></tt> is <tt>true</tt>,
else it is <tt>false</tt>.
</p>

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

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

<p>
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 (possibly <i>cv</i>-qualified) class or
union type (or array thereof) with a trivial default constructor then
<tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

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

<p>
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
(possibly <i>cv</i>-qualified) class or union type with a trivial copy
constructor then <tt><i>b</i></tt> is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

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

<p>
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 (possibly <i>cv</i>-qualified) class or
union type with a trivial copy constructor then <tt><i>b</i></tt> is
<tt>true</tt>, else it is <tt>false</tt>.
</p>

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

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

<p>
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
(possibly <i>cv</i>-qualified) class or union type (or array thereof) with a
trivial destructor then <tt><i>b</i></tt> is <tt>true</tt>, else it is
<tt>false</tt>.
</p>

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

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

<p>
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 (possibly
<i>cv</i>-qualified) 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>.
</p>

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

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

<p>
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 (possibly
<i>cv</i>-qualified) 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>.
</p>

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

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

<p>
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 (possibly
<i>cv</i>-qualified) class or union type with an 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 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>.
</p>

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

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

<p>
If <tt>T</tt> is a class type with a virtual destructor then <tt><i>b</i></tt>
is <tt>true</tt>, else it is <tt>false</tt>.
</p>

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

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

<p>
The traits in this section model <i>BinaryTypeTrait</i>. 
</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>
If <tt>T</tt> and <tt>U</tt> are the same type, with identical
<i>cv</i>-qualifications, then <tt><i>b</i></tt> is <tt>true</tt>, else it is
<tt>false</tt>.
</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>
If <tt>Base</tt> is either the same type as <tt>Derived</tt> or is a base class
of <tt>Derived</tt>, then <tt><i>b</i></tt> is <tt>true</tt>, else it is
<tt>false</tt>.
</p>

<p>
Requires: <tt>T</tt> is a complete type, an array type of unknown bounds of a complete
type, or is a <tt>void</tt> type.
</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>
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>.
</p>

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

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

<blockquote class="note">
<p>
The wording above assumes acceptance of the rvalue reference proposal.  However the
definition could remain the same, but have more complicated wording without using
<tt>add_rvalue_reference</tt> or requiring rvalue references in the language.
</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 either
an lvalue or an rvalue, 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
is_convertible&lt;unique_ptr&lt;Derived&gt;&amp;&amp;, unique_ptr&lt;Base&gt;&gt;::value;  // true,  From is rvalue
</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>.
</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 or <tt>function
reference</tt> types, but not to a <tt>function</tt> type.
</p>
</blockquote>

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

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

<p>
The trait <tt>alignment_of</tt> models <i>UnaryTypeTrait</i>.
The trait <tt>aligned_storage</tt> models <i>TransformationTrait</i>. 
</p>

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

<p>
<tt><i>v</i></tt> is the number of bytes of the alignment of objects of type
<tt>T</tt> (i.e. the <i>alignment requirement</i> [basic.types]); an object of
type <tt>T</tt> may be allocated at an address that is a multiple of its
alignment.  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.
</p>

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

<blockquote><pre>
template &lt;size_t Len, size_t Align = <i>most_stringent_alignment_requirement</i>&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>Len</tt> and
whose alignment requirement is a divisor of <tt>Align</tt>.  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].
</p>

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

<p>
Invariant: <tt>alignment_of&lt;aligned_storage&lt;Len, Align&gt;::type&gt;::value == Align</tt> for
any <tt>Align</tt> that meets the requirements of <tt>aligned_storage</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 <tt>Align</tt>.
</p>

<p>
It is possible that <tt>aligned_storage&lt;Len, Align&gt;</tt> supports greater
values of <tt>Align</tt> than is implied by the defaulted value of
<tt>Align</tt>, by returning types which are outside of the definition of C++
(e.g. to support page-aligned memory). However the invariant above shall hold in
any case.  And the client shall be assured that if <tt>Align</tt> is defaulted,
then the type returned by <tt>aligned_storage</tt> shall have compatible
alignment requirements for any C++ object type.
</p>

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

<blockquote class="note">
<p>
The defaulted second argument 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 Robert Klarer are gratefully acknowledged.
</p>

</body>
</html>
