<html>

<head>
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Additional Type-Traits for C++0x</title>
<style type="text/css">
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
</style>
</head>

<body>

<div align="left">
  <table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="579">
    <tr>
      <td width="153" align="left" valign="top">Document number:</td>
      <td width="426">N2984=09-0174</td>
    </tr>
    <tr>
      <td width="153" align="left" valign="top">Date:</td>
      <td width="426">2009-10-23</td>
    </tr>
    <tr>
      <td width="153" align="left" valign="top">Project:</td>
      <td width="426">Programming Language C++, Library Working Group</td>
    </tr>
    <tr>
      <td width="153" align="left" valign="top">Reply-to:</td>
      <td width="426">Beman Dawes &lt;bdawes at acm dot org&gt;<br>
      Daniel Krgler &lt;daniel.kruegler at googlemail dot <wbr />com&gt;<br>
      Alisdair Meredith<span class="gI"><span class="go"> &lt;public at alisdairm 
      dot net&gt;</span></span></td>
    </tr>
  </table>
</div>

<h1>Additional Type Traits for C++0x (Revision 1)</h1>

<h2>Introduction</h2>

<p>The C++ committee's Library Working Group (LWG) asked in Frankfurt for a 
proposal unifying LWG requests for additional type traits in light 
of the&nbsp; removal of the concepts language feature from C++0x.</p>

<h2>Revision history</h2>

<p><b>N2984</b> - Revision 1</p>

<ul>
  <li>Added <tt>is_constructible</tt></li>
  <li>Added <tt>is_nothrow_constructible</tt></li>
  <li>Made i<tt>s_convertible</tt> a synonym for a two argument <tt>is_constructible</tt> </li>
  <li>Renamed <tt>enum_base</tt> as <tt>underlying_type</tt></li>
  <li>Added Acknowledgements</li>
</ul>

<p><b>N2947</b> - Initial version.</p>

<h2>Rationale</h2>

<h3>is_trivially_copyable</h3>

<p>LWG issue 
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2948.html#1174">1174</a>, submitted by Jason Merrill:</p>

<blockquote>
  <p>I've been implementing compiler support for <tt>is_standard_layout</tt>, 
  and noticed a few nits about 20.6.4.3 [meta.unary.prop]: </p>
  <ol>
    <li>There's no trait for &quot;trivially copyable type&quot;, which is now the 
    property that lets you do bitwise copying of a type, and therefore seems 
    useful to be able to query. <tt>has_trivial_assign</tt> &amp;&amp; <tt>
    has_trivial_copy_constructor</tt> &amp;&amp; <tt>has_trivial_destructor</tt> is 
    similar, but not identical, specifically with respect to const types. </li>
    <li><tt>has_trivial_copy_constructor</tt> and <tt>has_trivial_assign</tt> 
    lack the &quot;or an array of such a class type&quot; language that most other traits 
    in that section, including <tt>has_nothrow_copy_constructor</tt> and <tt>
    has_nothrow_assign</tt>, have; this seems like an oversight. </li>
  </ol>
</blockquote>
<p><i>[ See the thread starting with c++std-lib-24420 for further discussion. ]</i></p>

<p><code>is_trivially_copyable</code> is believed to require compiler support.</p>

<h3>is_literal_type</h3>

<p>LWG issue 
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2948.html#719">719</a>, submitted by Daniel Krgler:</p>

<blockquote>
  <p>Since the inclusion of <tt>constexpr</tt> in the standard draft N2369 we 
  have a new type category &quot;literal&quot;, which is defined in 3.9 [basic.types]/p.11:
  </p>
  <blockquote>
    <p>-11- A type is a <i>literal type</i> if it is: </p>
    <ul>
      <li>a scalar type; or</li>
      <li>a class type (clause 9) with<ul>
        <li>a trivial copy constructor,</li>
        <li>a trivial destructor,</li>
        <li>a trivial default constructor or at least one constexpr constructor 
        other than the copy constructor,<br>
        and</li>
        <li>all non-static data members and base classes of literal types; or</li>
      </ul>
      </li>
      <li>an array of literal type.</li>
    </ul>
  </blockquote>
  <p>I strongly suggest that the standard provides a type traits for literal 
  types in 20.6.4.3 [meta.unary.prop] for several reasons: </p>
  <ol type="a">
    <li>To keep the type traits in sync with the types defined in the core 
    language.</li>
    <li>I see many reasons for programmers to use this trait in template code to 
    provide optimized template definitions for these types, see below.</li>
    <li>A user-provided definition of this trait is practically impossible to 
    write portably.</li>
  </ol>
  <p>The special problem of reason (c) is that I don't see currently a way to 
  portably test the condition for literal class types: </p>
  <blockquote>
    <ul>
      <li>...at least one constexpr constructor other than the copy constructor,</li>
    </ul>
  </blockquote>
</blockquote>

<p><code>is_literal_type</code> is believed to require compiler support.</p>

<p>The proposed name is <code>is_literal_type</code>, rather than <code>
is_literal</code>, because <i>literal</i> and <i>literal type</i> have different 
core language meanings. It was judged better to be clear even at the cost of 
being inconsistent with the other names.</p>

<h3>is_nothrow_constructible</h3>

<p>This is a critical trait that came out of exception-safety considerations 
discussed in
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2953.html#Proposal">N2953</a>,
<i>Defining Move Special Member Functions</i>, given the possible presence of 
throwing and non-throwing copy/move operations.</p>

<p>From
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2953.html#Proposal">N2953</a>:</p>

<blockquote>

<p>&quot;However, throwing moves are problematic within the library, and some library 
specifications prohibit throwing moves. To enable conditional definition of move 
operations within the library, we add an <code>is_nothrow_constructible</code> 
variadic type trait.&quot;</p>

</blockquote>

<p><code>is_nothrow_constructible</code> is believed to require compiler 
support.</p>

<h3>is_constructible</h3>

<p><code>is_constructible</code> is the foundation upon which <code>
is_nothrow_constructible</code> and <tt>is_explictly_convertible</tt> are built.</p>

<p><code>is_constructible</code> is believed to require compiler support.</p>

<p>Omitting <code>is_constructible</code> in the presence of <code>
is_nothrow_constructible</code> would be inconsistent with other traits that 
have an i<code>s_nothrow_*</code> counterpart.</p>

<p>The cost of specifying this additional trait is outweighed by the consistency 
concern, and to satisfy user-expectations. Additionally, the trickiest part of 
the specification of <code>is_nothrow_constructible</code> is the <code>
is_constructible</code> subpart. So this work has to be done anyhow.</p>

<h3>is_explicitly_convertible</h3>

<p>LWG issue 
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2942.html#750">750</a>, submitted by Alisdair Meredith:</p>

<blockquote>

<p>The current definition for <tt>is_convertible</tt> requires that the type be 
implicitly convertible, so explicit constructors are ignored.</p>

<p>With the pending arrival of explicit conversion functions though, I'm 
wondering if we want an additional trait, <tt>is_explictly_convertible</tt>?</p>

</blockquote>

<p>Several LWG members have commented that they believe such a trait would be 
useful.</p>

<p><code>is_explicitly_convertible</code> is believed to require compiler 
support unless <code>is_constructible</code> is available.</p>

<h3>underlying_type</h3>

<p>LWG issue 
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2948.html#1055">1055</a>, addressing CD-1comment UK 98:</p>

<blockquote>

<p>It would be useful to be able to determine the underlying type of an 
arbitrary enumeration type. This would allow safe casting to an integral type 
(especially needed for scoped enums, which do not promote), and would allow use 
of <tt>numeric_limits</tt>. In general it makes generic programming with 
enumerations easier.</p>

</blockquote>

<p><code>underlying_type</code> is believed to require compiler support.</p>

<h2>Proposed wording</h2>

<p><i>To 20.6.2 Header &lt;type_traits&gt; synopsis [meta.type.synop], add as 
indicated:</i></p>

<blockquote>

<pre>namespace std {

// 20.6.3, helper class:
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;

// 20.6.4.1, primary type categories:
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_lvalue_reference;
template &lt;class T&gt; struct is_rvalue_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;

// 20.6.4.2, composite type categories:
template &lt;class T&gt; struct is_reference;
template &lt;class T&gt; struct is_arithmetic;
template &lt;class T&gt; struct is_fundamental;
template &lt;class T&gt; struct is_object;
template &lt;class T&gt; struct is_scalar;
template &lt;class T&gt; struct is_compound;
template &lt;class T&gt; struct is_member_pointer;

// 20.6.4.3, type properties:
template &lt;class T&gt; struct is_const;
template &lt;class T&gt; struct is_volatile;
template &lt;class T&gt; struct is_trivial;
<ins>template &lt;class T&gt; struct is_trivially_copyable;</ins>
template &lt;class T&gt; struct is_standard_layout;
template &lt;class T&gt; struct is_pod;
<ins>template &lt;class T&gt; struct is_literal_type;</ins>
template &lt;class T&gt; struct is_empty;
template &lt;class T&gt; struct is_polymorphic;
template &lt;class T&gt; struct is_abstract;
<ins>template &lt;class T, class... Args&gt; struct is_constructible;</ins>
<ins>template &lt;class T, class... Args&gt; struct is_nothrow_constructible;</ins>
template &lt;class T&gt; struct has_trivial_default_constructor;
template &lt;class T&gt; struct has_trivial_copy_constructor;
template &lt;class T&gt; struct has_trivial_assign;
template &lt;class T&gt; struct has_trivial_destructor;
template &lt;class T&gt; struct has_nothrow_default_constructor;
template &lt;class T&gt; struct has_nothrow_copy_constructor;
template &lt;class T&gt; struct has_nothrow_assign;
template &lt;class T&gt; struct has_virtual_destructor;
template &lt;class T&gt; struct is_signed;
template &lt;class T&gt; struct is_unsigned;
template &lt;class T&gt; struct alignment_of;
template &lt;class T&gt; struct rank;
template &lt;class T, unsigned I = 0&gt; struct extent;

// 20.6.5, type relations:
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;
<ins>template &lt;class From, class To&gt; struct is_explicitly_convertible;</ins>

// 20.6.6.1, const-volatile modifications:
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;

// 20.6.6.2, reference modifications:
template &lt;class T&gt; struct remove_reference;
template &lt;class T&gt; struct add_lvalue_reference;
template &lt;class T&gt; struct add_rvalue_reference;

// 20.6.6.3, sign modifications:
template &lt;class T&gt; struct make_signed;
template &lt;class T&gt; struct make_unsigned;

// 20.6.6.4, array modifications:
template &lt;class T&gt; struct remove_extent;
template &lt;class T&gt; struct remove_all_extents;
// 20.6.6.5, pointer modifications:
template &lt;class T&gt; struct remove_pointer;
template &lt;class T&gt; struct add_pointer;

// 20.6.7, other transformations:
template &lt;std::size_t Len, std::size_t Align&gt; struct aligned_storage;
template &lt;std::size_t Len, class... Types&gt; struct aligned_union;
template &lt;class T&gt; struct decay;
template &lt;bool, class T = void&gt; struct enable_if;
template &lt;bool, class T, class F&gt; struct conditional;
template &lt;class... T&gt; struct common_type;
<ins>template &lt;class&nbsp;T&gt; struct underlying_type;</ins>

} // namespace std</pre>

</blockquote>

<p><i>To 20.6.4.3 Type properties [meta.unary.prop], table </i>Type property 
predicates<i>, add rows:</i></p>

<blockquote>

<table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="95%">
  <tr>
    <td width="33%"><b>Template</b></td>
    <td width="33%"><b>Condition</b></td>
    <td width="34%"><b>Preconditions</b></td>
  </tr>
  <tr>
    <td valign="top" width="33%"><code>template &lt;class T&gt;<br>
    struct is_trivially_copyable;</code></td>
    <td valign="top" width="33%"><code>T</code> is a trivially copyable type ([basic.types]) </td>
    <td width="34%"><code>T</code> shall be a complete type,
    an array of unknown
    bound, or (possibly
    cv-qualified) <code>void</code>.</td>
  </tr>
  <tr>
    <td valign="top" width="33%"><code>template &lt;class T&gt;<br>
    struct is_literal_type;</code></td>
    <td valign="top" width="33%"><code>T</code> is a literal type ([basic.types]) </td>
    <td width="34%"><code>T</code> shall be a complete type,
    an array of unknown
    bound, or (possibly
    cv-qualified) <code>void</code>.</td>
  </tr>
  <tr>
    <td valign="top" width="33%"><tt>template &lt;class T, class... Args&gt; struct 
    is_constructible;</tt></td>
    <td valign="top" width="33%"><i>See below</i></td>
    <td width="34%"><tt>T</tt> and all types in the parameter pack <tt>Args</tt> 
    shall be complete types, arrays of unknown bound, or (possibly cv-qualified)
    <tt>void</tt> types.</td>
  </tr>
  <tr>
    <td valign="top" width="33%"><tt>template &lt;class T, class... Args&gt; struct 
    is_nothrow_constructible;</tt></td>
    <td valign="top" width="33%"><tt>is_constructible&lt;T, Args...&gt;::value</tt> is
    <tt>true</tt> and the expression <i>CE</i>, as defined below, is known not 
    to throw any exceptions.</td>
    <td width="34%"><tt>T</tt> and all types in the parameter pack <tt>Args</tt> 
    shall be complete types, arrays of unknown bound, or (possibly cv-qualified)
    <tt>void</tt> types.</td>
  </tr>
</table>

</blockquote>

<p><i>To 20.6.4.3 Type properties [meta.unary.prop], before table </i>Type 
property queries<i>, add:</i></p>

<blockquote>
  <p>Given the following function prototype: </p>
  <blockquote>
    <pre>template &lt;class T&gt;
typename add_rvalue_reference&lt;T&gt;::type create();</pre>
  </blockquote>
  <p>the predicate condition for a template specialization <tt>
  is_constructible&lt;T, Args...&gt;</tt> shall be satisfied, if and only if the 
  following expression <i>CE</i> would be well-formed: </p>
  <ul>
    <li>if <tt>sizeof...(Args) == 1</tt> the expression:
    <blockquote>
      <pre>static_cast&lt;T&gt;(create&lt;Args&gt;()...)</pre>
    </blockquote>
    </li>
    <li>otherwise the expression:
    <blockquote>
      <pre>T(create&lt;Args&gt;()...)</pre>
    </blockquote>
    </li>
  </ul>
</blockquote>

<p><i>To 20.6.5 Relationships between types [meta.rel], table  </i>Type 
relationship predicates<i>, add row:</i></p>

<blockquote>

<table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="95%">
  <blockquote>
    <blockquote>
  <tr>
    <td width="33%"><b>Template</b></td>
    <td width="33%"><b>Condition</b></td>
    <td width="34%"><b>Comments</b></td>
  </tr>
  <tr>
    <td valign="top" width="33%"><code>template &lt;class From, class To&gt;<br>
    struct is_explicitly_convertible;</code></td>
    <td valign="top" width="33%"><tt>is_constructible&lt;To, From&gt;::value</tt></td>
    <td width="34%" valign="top"><code>is_explicitly_convertible</code> is a 
    synonym for a two-argument <tt>is_constructible.</tt> An implementation may 
    define it as a template alias.</td>
  </tr>
    </blockquote>
  </blockquote>
  </table>

</blockquote>

<p><i>To 20.6.7 Other transformations [meta.trans.other], table  </i>Other 
transformations<i>, add row:</i></p>

<blockquote>

<table border="1" cellpadding="3" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="95%">
  <tr>
    <td width="349"><b>Template</b></td>
    <td width="350"><b>Condition</b></td>
    <td width="350"><b>Comments</b></td>
  </tr>
  <tr>
    <td valign="top" width="349"><code>template &lt;class T&gt;<br>
    struct underlying_type;</code></td>
    <td valign="top" width="350"><tt>T</tt> shall be an enumeration type ([dcl.enum])</td>
    <td width="350">The member typedef <tt>type</tt> shall name the underlying 
    type of the enum <tt>T</tt>.</td>
  </tr>
  </table>

</blockquote>

<h2>Acknowledgements</h2>
<p>Howard Hinnant, Lawrence Crowl, and Pablo Halpern contributed ideas and 
discussions leading to this proposal.</p>

<hr>
<p>&nbsp;</p>

</body>

</html>