<html>
<head>
<title>P3247R2: Deprecate the notion of trivial types</title>

<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">

<style type="text/css">
  ins { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  .new { text-decoration:none; font-weight:bold; background-color:#D0FFD0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }  
  .del { text-decoration:line-through; background-color:#FFC0C0 }  
  strong { font-weight: inherit; color: #2020ff }
  table, td, th { border: 1px solid black; border-collapse:collapse; padding: 5px }
</style>
</head>

<body>
ISO/IEC JTC1 SC22 WG21 P3247R2<br/>
Jens Maurer &lt;Jens.Maurer@gmx.net><br/>
Target audience: LWG, CWG<br/>
2024-10-28+<br/>

<h1>P3247R2: Deprecate the notion of trivial types</h1>

<h2>Introduction</h2>

<p>
The core language defines "trivial types", and in particular, trivial
class types, even though that concept is used mainly for the
definition of the library type trait <TT>is_trivial</TT>.  This
proposal deprecates the type trait <TT>is_trivial</TT> and moves the
definition of "trivial type" next to the new location of the
specification of the type trait.
</p>

<p>
This proposal follows the footsteps of "POD", deprecated with
<A HREF="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0767r1.html">P0767R1</A> (November, 2017).

<p>
This proposal partially addresses
<A HREF="https://cplusplus.github.io/CWG/issues/1808.html">core issue 1808</A>.
</p>

<h2>History</h2>

<ul>
<li>R1: Adjust two more uses of "trivial class" in the standard
library; add forgotten change to [meta.type.synop].</li>
<li>R2: Adjust wording to clarify trivial default constructors. Add
rationale per request of LEWG. Add wording adjustment for
[inplace.vector.overview].</li>
</ul>

<h2>Rationale</h2>

<p>The trait <code>is_trivial</code> mixes two checks: Is the class
trivially copyable, and is it trivially default constructible?  Those
checks are needed in different situations.  A survey of existing uses
of <code>is_trivial</code> shows that it is often used in situations
where one of the properties is needed, not both.  Furthermore, the
check whether a class is trivially copyable might not actually be the
appropriate check, either. For example:</p>
<pre>
struct S {
  const int i;
};
</pre>

<p><code>S</code> is trivially copyable, yet it is not assignable.  A
user seeking to replace copy-assignment with <code>memcpy</code>
should use <code>is_trivially_copy_assignable</code> for the check;
checking just <code>is_trivial</code> or <code>is_trivially_copyable</code>
as a precondition for assignment would underconstrain the user
code.</p>

<p>Therefore, it is best to deprecate (and eventually
remove) <code>is_trivial</code> to encourage the appropriate traits
checks in user code.</p>

<p>Also, <TT>is_trivial</TT> does not assert that any of the related
constructors be public.  However, that is a necessity to be able to
actually use a constructor in usual code.  The wording changes below
therefore change the library specification to
use <TT>std::is_trivially_default_constructible_v</TT>.  Note that
"trivially copyable" is retained, even though it also lacks any
assertion that the related copy/move operations be public.  This
implies that <TT>std::string</TT> needs to always
use <TT>std::memcpy</TT> to copy its elements, because there is no
guarantee that any of the constructors contributing to "trivially
copyable" be public.  If that situation is unsatisfying, interested
parties might consider filing an LWG issue.</p>

<h2>Wording changes</h2>

<p>Remove from 6.9.1 [basic.types.general] paragraph 9:</p>

<blockquote>
[...] <del>Scalar types, trivial class types (11.2 [class.prop]),
arrays of such types, and cv-qualified versions of these types are
collectively called trivial types.</del> [...]
</blockquote>

<p>Change in 11.2 [class.prop] paragraph 2:</p>

<blockquote>
<del>A trivial class is a class that is trivially copyable and has one
or more eligible default constructors (11.4.5.2), all of which are
trivial.  [Note 1: In particular, a trivially copyable or trivial
class does not have virtual functions or virtual base classes. — end
note] </del>
</blockquote>

<p>Change in 11.2 [class.prop] paragraph 7:</p>

<blockquote>
[Example 2 :
<pre>
struct N {   // neither <del>trivial</del> <ins>trivially copyable</ins> nor standard-layout
  int i;
  int j;
  virtual ~N();
};

struct T {  // <del>trivial</del> <ins>trivially copyable</ins> but not standard-layout
  int i;
private:
  int j;
};

struct SL {  // standard-layout but not <del>trivial</del> <ins>trivially copyable</ins>
  int i;
  int j;
  ~SL();
};

struct POD {  // both <del>trivial</del> <ins>trivially copyable</ins> and standard-layout
  int i;
  int j;
};
</pre>
— end example]
</blockquote>

<p>Change in 11.9.5 [class.cdtor] paragraph 1:</p>

<blockquote>
<pre>
extern X xobj;
int* p3 = &xobj.i;    // OK, <del>X is a trivial class</del> <ins>all constructors of X are trivial</ins>
X xobj;
</pre>
</blockquote>

<p>Change in 17.2.4 [support.types.layout] paragraph 5:</p>

<blockquote>
The type <TT>max_align_t</TT> is a <del>trivial</del> <ins>trivially
copyable</ins> standard-layout type whose alignment requirement is at
least as great as that of every scalar type, and whose alignment
requirement is supported in every context (6.7.6
[basic.align]). <ins><TT>std::is_trivially_default_constructible_v&lt;max_align_t&gt;</TT> is <TT>true</TT>.</ins>
</blockquote>

<p>Change in 23.1 [strings.general] paragraph 1:</p>

<blockquote>
This Clause describes components for manipulating sequences of any
non-array <del>trivial</del> <ins>trivially copyable</ins>
standard-layout (6.8.1) type <ins><TT>T</TT>
where <TT>is_trivially_default_constructible_v&lt;T&gt;</TT>
is <TT>true</TT></ins>. Such types are called char-like types, and
objects of char-like types are called char-like objects or simply
characters.
</blockquote>

<p>Remove from 21.3.3 [meta.type.synop]:</p>

<blockquote>
<pre class="del">
template&lt;class T&gt; struct is_trivial;
</pre>
...
<pre class="del">
template&lt;class T&gt;
  constexpr bool is_trivial_v = is_trivial&lt;T&gt;::value;
</pre>
</pre>
</blockquote>

<p>Remove from 23.3.5.4 [meta.unary.prop]:</p>

<blockquote>
<table>
<tr class="del">
<td>
<pre>
template&lt;class T>
struct is_trivial;
</pre>
</td>
<td>
<TT>T</TT> is a trivial type (6.9.1 [basic.types.general])
</td>
<td>
<TT>remove_all_extents_t&lt;T></TT> shall be a complete type
or <I>cv</I> <TT>void</TT>.
</td>
</tr>
</table>
</blockquote>

<p>Change in 23.3.14.1 [inplace.vector.overview]:</p>

<blockquote>
For any N &gt; 0,
if
<del><TT>is_trivial_v&lt;T&gt;</TT></del> <ins><TT>T</TT> is not
trivially copyable or
<TT>is_trivially_default_constructible_v&lt;T&gt;</TT></ins> is
<TT>false</TT>, then no <TT>inplace_vector&lt;T, N&gt;</TT> member
functions are usable in constant expressions.
</blockquote>

<p>Change in 24.7.3.4.4 [mdspan.layout.policy.overview] paragraphs 1 and 2:</p>

<blockquote>
<p>Each of <TT>layout_left</TT>, <TT>layout_right</TT>,
and <TT>layout_stride</TT> <ins>, as well as each specialization
of <TT>layout_left_padded</TT> and <TT>layout_right_padded</TT>,</ins>
meets the layout mapping policy requirements and is
a <del>trivial</del> <ins>trivially copyable</ins> type.
<ins>Furthermore, <TT>is_trivially_default_constructible_v&lt;T&gt;</TT>
is <TT>true</TT> for any such type <TT>T</TT></ins>.
</p>

<p class="del">Each specialization of layout_left_padded and
layout_right_padded meets the layout mapping policy requirements and
is a trivial type.
</blockquote>

<p>Change in D.14 [depr.meta.types]:</p>

<blockquote>
<pre>
namespace std {
<ins>  template&lt;class T> struct is_trivial;
  template&lt;class T> constexpr bool is_trivial_v = is_trivial&lt;T>::value;</ins>
  template&lt;class T> struct is_pod;
  template&lt;class T> constexpr bool is_pod_v = is_pod&lt;T>::value;
...
}
</pre>

<p>The behavior of a program...</p>

<p class="new">A <I>trivial class</I> is a class that is trivially
copyable and has one or more eligible default constructors, all of
which are trivial.  [Note: In particular, a trivial class does not
have virtual functions or virtual base classes. — end note]
A <I>trivial type</I> is a scalar type, a trivial class, an array of
such a type, or a cv-qualified version of one of these types.
</p>

<p>A POD class is a class that ...</p>

<pre class="new">
  template&lt;class T> struct is_trivial;
</pre>

<p class="new">Preconditions: <TT>remove_all_extents_t&lt;T></TT>
shall be a complete type or <I>cv</I> <TT>void</TT>.</p>

<p class="new">Remarks: <TT>is_trivial&lt;T></TT> is a
Cpp17UnaryTypeTrait (21.3.2 [meta.rqmts]) with a base characteristic
of <TT>true_type</TT> if <TT>T</TT> is a trivial type,
and <TT>false_type</TT> otherwise.
</p>

<p class="new">[Note: It is unspecified whether a closure type
(7.5.5.2 [expr.prim.lambda.closure]) is a trivial type. — end
note]</p>

<pre>
  template&lt;class T> struct is_pod;
</pre>

</blockquote>

</body>
</html>
