<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.5: http://docutils.sourceforge.net/" />
<title>Defaulting non-public special member functions on first declaration</title>
<meta name="date" content="2010-02-03" />
<meta name="authors" content="Ville Voutilainen &lt;ville.voutilainen&#64;gmail.com&gt;" />
<style type="text/css">

/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 5196 2007-06-03 20:25:28Z wiemann $
:Copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.

See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/

/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
  border: 0 }

table.borderless td, table.borderless th {
  /* Override padding for "table.docutils td" with "! important".
     The right padding separates the table cells. */
  padding: 0 0.5em 0 0 ! important }

.first {
  /* Override more specific margin styles with "! important". */
  margin-top: 0 ! important }

.last, .with-subtitle {
  margin-bottom: 0 ! important }

.hidden {
  display: none }

a.toc-backref {
  text-decoration: none ;
  color: black }

blockquote.epigraph {
  margin: 2em 5em ; }

dl.docutils dd {
  margin-bottom: 0.5em }

/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
  font-weight: bold }
*/

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

/* Uncomment (and remove this text!) to get reduced vertical space in
   compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
  margin-bottom: 0.5em }

div.compound .compound-last, div.compound .compound-middle {
  margin-top: 0.5em }
*/

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em ;
  margin-right: 2em }

div.footer, div.header {
  clear: both;
  font-size: smaller }

div.line-block {
  display: block ;
  margin-top: 1em ;
  margin-bottom: 1em }

div.line-block div.line-block {
  margin-top: 0 ;
  margin-bottom: 0 ;
  margin-left: 1.5em }

div.sidebar {
  margin: 0 0 0.5em 1em ;
  border: medium outset ;
  padding: 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
  margin-top: 0.4em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

hr.docutils {
  width: 75% }

img.align-left {
  clear: left }

img.align-right {
  clear: right }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em }

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

span.section-subtitle {
  /* font-size relative to parent (h1..h6 element) */
  font-size: 80% }

table.citation {
  border-left: solid 1px gray;
  margin-left: 1px }

table.docinfo {
  margin: 2em 4em }

table.docutils {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.footnote {
  border-left: solid 1px black;
  margin-left: 1px }

table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

table.docutils th.field-name, table.docinfo th.docinfo-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap ;
  padding-left: 0 }

h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
  font-size: 100% }

ul.auto-toc {
  list-style-type: none }

</style>
</head>
<body>
<div class="document" id="defaulting-non-public-special-member-functions-on-first-declaration">
<h1 class="title">Defaulting non-public special member functions on first declaration</h1>
<table class="docinfo" frame="void" rules="none">
<col class="docinfo-name" />
<col class="docinfo-content" />
<tbody valign="top">
<tr><th class="docinfo-name">Date:</th>
<td>2010-02-03</td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>N3023=10-0013</td></tr>
<tr><th class="docinfo-name">Authors:</th>
<td>Ville Voutilainen &lt;<a class="reference external" href="mailto:ville.voutilainen&#64;gmail.com">ville.voutilainen&#64;gmail.com</a>&gt;</td></tr>
</tbody>
</table>
<div class="abstract topic">
<p class="topic-title first">Abstract</p>
<p>The resolution of Core Issue 906 forbids defaulting a non-public
special member function on its first declaration. I believe
this resolution to be incorrect, and this document explains why.
This document proposes that defaulting a non-public special
member function on its first declaration is an important part
of design vocabulary, and should not be considered as something
that affects triviality. Defaulting should retain triviality,
or retain the lack of triviality, and people shouldn't expect
defaulting to bring forth triviality. Furthermore, non-public
special member functions defaulted on first declaration should
not be considered user-provided.</p>
</div>
<p>I wish to thank Daniel Krügler for performing a sanity check for this
paper, and Lawrence Crowl for reviewing the paper and providing feedback
and suggestions for improvement.</p>
<div class="section" id="background">
<h1>Background</h1>
<p>N2346 states that &quot;A special member function is user-provided if it
is user-declared and not explicitly defaulted on its first declaration.&quot;
Further, N3000 states in 12.8 Copying class objects [class.copy] p6 that
&quot;A copy constructor for class X is trivial if it is not user-provided&quot;.
Therefore, I would assume that if it's allowed to default a non-public
copy constructor on its first declaration, a non-public
copy constructor could be trivial. For constructors, 12.1 Constructors
[class.ctor] p5 states that &quot;A default constructor is trivial if it is
not user-provided&quot;. Therefore, I'd assume that if it's allowed to default
a non-public constructor on its first declaration, a non-public
default constructor could be trivial.</p>
<p>The current status quo is that in order to be defaulted on the
first declaration, a special member function must be public.
During the discussion of Core Issue 906 in Santa Cruz it was
suggested by John Spicer that triviality should be made more
explicit by forcing the user to do the defaulting after the first
declaration, assuming that defaulting a non-public member function
will remove triviality because such a function would be considered
user-provided.</p>
<p>Jason Merrill and I were of the opinion that access should not be
the deciding factor when allowing defaulting on the first declaration,
but it should be decided on whether the defaulted special member
function is considered user-provided. It seems to me that N2346
strongly suggests that a defaulted special member function should
not be considered user-provided, and thus non-public member functions
should not affect triviality if they are defaulted.</p>
<p>Jens Maurer thought in message 15490 that a base class with
a protected copy constructor makes a derived class not trivially
copyable, because it has a subobject that is not trivially copyable.
Mike Miller asked for a use case, which was provided later in
reflector discussions, in message 15492 on the core reflector.</p>
</div>
<div class="section" id="the-problem-cases-that-should-be-allowed-and-trivial">
<h1>The problem, cases that should be allowed and trivial</h1>
<p>I think it's problematic that non-public special member functions
can't be defaulted on their first declaration. The defaulting is
something that people do when they want to retain triviality if
possible. The access control is orthogonal to that, because
access control in this case is a design tool. Forbidding defaulting
on first declaration seems to restrict the design vocabulary considerably.</p>
<p>Furthermore, regarding the concern by Jens Maurer, a base class with
a protected copy constructor is not CopyConstructible to begin with;
a derived class can be, however, if the derived class has a public
copy constructor. My take on that is that a derived class can be
trivially copyable, even if the base class alone would not be,
as long as the copy constructor of the base is accessible to the
derived class, and as long as neither copy constructor is user-provided.</p>
<p>This applies to all subobjects, a class aggregating a subobject
having a private copy constructor can still be trivially copyable
if the aggregating class is the friend of the aggregated class.</p>
<p>I shall repeat the use cases provided on the mailing list.
Let's first consider a case where a copy constructor is protected
and defaulted:</p>
<pre class="literal-block">
struct B
{
protected:
   B(const B&amp;) = default;
};

struct D : B
{
};
</pre>
<p>The use case for this defaulting would be that the user is
attempting to forbid slicing copies from D to B, but still
retaining triviality.</p>
<p>When the design evolves, the user decides that instances of
the base are harmful, so she modifies the base thus:</p>
<pre class="literal-block">
struct B
{
protected:
    B() = default;
    B(const B&amp;) = default;
};
</pre>
<p>There's still no reason for the user to assume that D
wouldn't be trivially copyable, because there's no user-provided
function in sight. D should also be trivially constructible,
for the same reason.</p>
<p>For other subobjects besides base classes, let's consider the following:</p>
<pre class="literal-block">
struct part
{
friend class aggregate;
private:
    part() = default;
    part(const part&amp;) = default;
};

struct aggregate
{
    part x;
};
</pre>
<p>I'd expect it to be perfectly reasonable for the user to assume
aggregate to be trivially copyable (and trivially constructible).</p>
</div>
<div class="section" id="some-cases-that-should-be-allowed-but-aren-t-trivial">
<h1>Some cases that should be allowed but aren't trivial</h1>
<p>Let's consider the following example:</p>
<pre class="literal-block">
struct base
{
    std::shared_ptr&lt;int&gt; member;
};
</pre>
<p>The implicitly declared copy constructor will not be trivial,
since shared_ptr's copy constructor isn't. Now, if this is a
base class that people don't want to have instances of, we
may write</p>
<pre class="literal-block">
struct base
{
    std::shared_ptr&lt;int&gt; member;
protected:
    base() = default;
    base(const base&amp;) = default;
};
</pre>
<p>This shouldn't affect the triviality in any way. Yet users expect
it to be allowed. While destructors work just fine with an empty
definition, copy constructors don't. Thus the brevity of being
able to default on first declaration seems superior to the alternatives.
Consider the following:</p>
<pre class="literal-block">
struct base
{
    std::shared_ptr&lt;int&gt; member;
protected:
    base(const base&amp;) {} // doesn't work at all!
};
</pre>
<p>Another, correct attempt would be this:</p>
<pre class="literal-block">
struct base
{
    std::shared_ptr&lt;int&gt; member;
protected:
    base(const base&amp;);
};

base::base(const base&amp;) = default; // tedious to write outside the class definition
</pre>
<p>According to my surveys, users understand that defaulting such a copy
constructor will not bring forth triviality. They also want to do
the defaulting concisely, and they don't want to be forced to write
it outside the class.</p>
</div>
<div class="section" id="discussion-about-the-solution">
<h1>Discussion about the solution</h1>
<p>Help is needed for drafting, because I don't know if it's sufficient
to just strike the requirement for a special member function defaulted
on its first declaration to be public.</p>
<p>I find it hard to agree with the intent of prohibiting defaulting
non-public special member functions on first declaration. It seems
to be a language mechanism that emphasizes cases where triviality
is not achieved. However, it should be noted that an implicitly
declared copy constructor is not ill-formed for classes that aren't
trivially copyable, so for the sake of consistency, I think defaulted
copy constructors should not be ill-formed in that case either,
whether public or not. And as suggested by this paper, I don't
think a protected or even private special member function should
result in loss of triviality, and most importantly, such a function
should definitely not be considered user-provided just because
it has different access than the implicitly declared function
would have.</p>
<p>I'm inclined to think it's a quality-of-implementation issue to diagnose
the lack of triviality, whether in the case of implicitly declared
special member functions or in the case of special member functions defaulted
on first declaration. I consider forbidding defaulting non-public
special member functions on first declaration to be overkill for
what it's seemingly trying to achieve, and I consider it grossly
incorrect from the design vocabulary point of view.</p>
</div>
</div>
</body>
</html>
