﻿<!DOCTYPE html>
<html>
<head>
<title>Disallowing Inaccessible Operators From Trivially Copyable</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* GitHub stylesheet for MarkdownPad (http://markdownpad.com) */
/* Author: Nicolas Hery - http://nicolashery.com */
/* Version: b13fe65ca28d2e568c6ed5d7f06581183df8f2ff */
/* Source: https://github.com/nicolahery/markdownpad-github */

/* RESET
=============================================================================*/

html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
}

/* BODY
=============================================================================*/

body {
  font-family: Helvetica, arial, freesans, clean, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  color: #333;
  background-color: #fff;
  padding: 20px;
  max-width: 960px;
  margin: 0 auto;
}

body>*:first-child {
  margin-top: 0 !important;
}

body>*:last-child {
  margin-bottom: 0 !important;
}

/* BLOCKS
=============================================================================*/

p, blockquote, ul, ol, dl, table, pre {
  margin: 15px 0;
}

/* HEADERS
=============================================================================*/

h1, h2, h3, h4, h5, h6 {
  margin: 20px 0 10px;
  padding: 0;
  font-weight: bold;
  -webkit-font-smoothing: antialiased;
}

h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code, h5 tt, h5 code, h6 tt, h6 code {
  font-size: inherit;
}

h1 {
  font-size: 28px;
  color: #000;
}

h2 {
  font-size: 24px;
  border-bottom: 1px solid #ccc;
  color: #000;
}

h3 {
  font-size: 18px;
}

h4 {
  font-size: 16px;
}

h5 {
  font-size: 14px;
}

h6 {
  color: #777;
  font-size: 14px;
}

body>h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
  margin-top: 0;
  padding-top: 0;
}

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  margin-top: 0;
  padding-top: 0;
}

h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
  margin-top: 10px;
}

/* LINKS
=============================================================================*/

a {
  color: #4183C4;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

/* LISTS
=============================================================================*/

ul, ol {
  padding-left: 30px;
}

ul li > :first-child, 
ol li > :first-child, 
ul li ul:first-of-type, 
ol li ol:first-of-type, 
ul li ol:first-of-type, 
ol li ul:first-of-type {
  margin-top: 0px;
}

ul ul, ul ol, ol ol, ol ul {
  margin-bottom: 0;
}

dl {
  padding: 0;
}

dl dt {
  font-size: 14px;
  font-weight: bold;
  font-style: italic;
  padding: 0;
  margin: 15px 0 5px;
}

dl dt:first-child {
  padding: 0;
}

dl dt>:first-child {
  margin-top: 0px;
}

dl dt>:last-child {
  margin-bottom: 0px;
}

dl dd {
  margin: 0 0 15px;
  padding: 0 15px;
}

dl dd>:first-child {
  margin-top: 0px;
}

dl dd>:last-child {
  margin-bottom: 0px;
}

/* CODE
=============================================================================*/

pre, code, tt {
  font-size: 12px;
  font-family: Consolas, "Liberation Mono", Courier, monospace;
}

code, tt {
  margin: 0 0px;
  padding: 0px 0px;
  white-space: nowrap;
  border: 1px solid #eaeaea;
  background-color: #f8f8f8;
  border-radius: 3px;
}

pre>code {
  margin: 0;
  padding: 0;
  white-space: pre;
  border: none;
  background: transparent;
}

pre {
  background-color: #f8f8f8;
  border: 1px solid #ccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px;
}

pre code, pre tt {
  background-color: transparent;
  border: none;
}

kbd {
    -moz-border-bottom-colors: none;
    -moz-border-left-colors: none;
    -moz-border-right-colors: none;
    -moz-border-top-colors: none;
    background-color: #DDDDDD;
    background-image: linear-gradient(#F1F1F1, #DDDDDD);
    background-repeat: repeat-x;
    border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
    border-image: none;
    border-radius: 2px 2px 2px 2px;
    border-style: solid;
    border-width: 1px;
    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
    line-height: 10px;
    padding: 1px 4px;
}

/* QUOTES
=============================================================================*/

blockquote {
  border-left: 4px solid #DDD;
  padding: 0 15px;
  color: #777;
}

blockquote>:first-child {
  margin-top: 0px;
}

blockquote>:last-child {
  margin-bottom: 0px;
}

/* HORIZONTAL RULES
=============================================================================*/

hr {
  clear: both;
  margin: 15px 0;
  height: 0px;
  overflow: hidden;
  border: none;
  background: transparent;
  border-bottom: 4px solid #ddd;
  padding: 0;
}

/* TABLES
=============================================================================*/

table th {
  font-weight: bold;
}

table th, table td {
  border: 1px solid #ccc;
  padding: 6px 13px;
}

table tr {
  border-top: 1px solid #ccc;
  background-color: #fff;
}

table tr:nth-child(2n) {
  background-color: #f8f8f8;
}

/* IMAGES
=============================================================================*/

img {
  max-width: 100%
}
</style>
</head>
<body>
<h1>Disallowing Inaccessible Operators From Trivially Copyable</h1>
<ul>
<li>Document Number : N4148</li>
<li>Date            : 2014-09-24</li>
<li>Project         : Programming Language C++, Evolution Working Group</li>
<li>Reply-to        : Matheus Izvekov <a href="&#x6d;&#97;&#x69;&#108;&#x74;&#x6f;&#x3a;&#109;&#105;&#x7a;&#x76;&#x65;&#107;&#x6f;&#118;&#x40;&#x67;&#x6d;&#97;&#x69;&#x6c;&#46;&#99;om">&#109;&#x69;&#122;&#118;&#101;&#x6b;&#111;&#118;&#x40;&#x67;&#109;&#97;&#x69;&#x6c;.&#99;o&#x6d;</a></li>
</ul>
<hr />
<h2>Summary</h2>
<p>This proposal aims to solve a serious flaw in the definition of the trivially copyable concept.
Presently, classes with deleted or inaccessible copy/move constructors, copy/move assignment operators and destructor are allowed to be trivially copyable, which might seem counterintuitive.</p>
<h2>The Problem</h2>
<p>When a class is trivially copyable, it is expected that this class can be copied without involving
any operators, by using for example <code>std::memcpy</code> to copy from one object to another. This can be highly advantageous when copying large arrays, as the whole array can be copied in just one call to <code>std::memcpy</code>, typically resulting in improved performance.</p>
<p>A generic algorithm can be written thus that elects to copy a given array either by
calling the copy constructor on each element or by copying the whole array with <code>std::memcpy</code>, depending on
the value of <code>std::is_trivially_copyable&lt;T&gt;::value</code>, where T is the array element type.</p>
<p>However there is a problem.
From the definition of trivially copyable ([class] paragraph 6):</p>
<pre><code>A trivially copyable class is a class that:
— has no non-trivial copy constructors (12.8),
— has no non-trivial move constructors (12.8),
— has no non-trivial copy assignment operators (13.5.3, 12.8),
— has no non-trivial move assignment operators (13.5.3, 12.8), and
— has a trivial destructor (12.4).
</code></pre>

<p>According to this definition, a class with all deleted or inaccessible copy/move constructors, copy/move assignment operators and destructor is trivially copyable.</p>
<p>This is problematic, because idiomatically it is expected that a class with all deleted copy constructors/operators
cannot be copied, that a class with all deleted move constructors/operators cannot be moved and that a class with a deleted destructor cannot be destroyed.</p>
<p>But when using an array of elements of such a class with the generic algorithm just hypothesized, the <code>std::memcpy</code>
path will be selected and it will not fail to compile, creating copies of objects which the user probably intended that cannot be copied, and in the process destroying the elements of the destination array, which the user
probably intended that cannot be destroyed.</p>
<h2>The Solution</h2>
<p>Strike the current definition of trivially copyable from [class] paragraph 6, and redefine it as:</p>
<pre><code>A trivially copyable class is a class that:
— has no non-trivial copy constructors, move constructors,
  copy assignment operators and move assignment operators (13.5.3, 12.8),

— either has a trivial, non-deleted and accessible
  copy constructor or move constructor (12.8),

— either has a trivial, non-deleted and accessible
  copy assignment operator or move assignment operator (13.5.3, 12.8), and

— has a trivial, non-deleted and accessible destructor (12.4).
</code></pre>

<h2>Acknowledgements</h2>
<p>Ville Voutilainen for discussing the problem on std-discussion and helping the author understand the nuances regarding deleted trivial copy constructors.</p>

</body>
</html>
<!-- This document was created with MarkdownPad, the Markdown editor for Windows (http://markdownpad.com) -->
