<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>

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

<title>Resolving Core Issue #1331 (const mismatch with defaulted copy constructor)</title>

<style type="text/css">
  code {
    white-space:pre;
  }
  p {
    text-align:justify;
  }
  ins {
    background-color:#A0FFA0;
  }
  del {
    background-color:#FFA0A0;
  }
  blockquote.std {
    background-color:#F0F0F0;
  }
  blockquote.std ul {
    list-style-type: '— ';
  }
</style>
</head><body>
<address style="text-align: left;">
Document number: P0641R1<br/>
Date: 2017-07-24<br/>
Project: Programming Language C++<br/>
Audience: Evolution Working Group<br/>
Reply-to: <a href="mailto:daniel.kruegler@gmail.com">Daniel Kr&uuml;gler</a>, <a href="mailto:botond@mozilla.com">Botond Ballo</a>
</address>
<hr>
<h1 style="text-align: center;">Resolving Core Issue #1331 (<code>const</code> mismatch with defaulted copy constructor)</h1>

<ul>
<li><a href="#Revision_history">Revision History</a></li>
<li><a href="#Motivation">Motivation</a></li>
<li><a href="#Analysis">Analysis</a></li>
<li><a href="#Proposed_resolution">Proposed Resolution</a></li>
<li><a href="#Proposed_wording">Proposed Wording</a></li>
<li><a href="#Issues_resolved">Issues Resolved</a></li>
</ul>

<h2><a name="Revision_history"></a>Revision History</h2>
<p>Changes since P0641R0:</p>
<ul>
  <li>Updated proposed wording to address comments from CWG review.</li>
  <li>Fixed outdated section numbers and typos.</li>
</ul>

<h2><a name="Motivation"></a>Motivation</h2>
<p>
If you have a class with a copy constructor whose parameter type is reference-to-nonconst:</p>
<code>
  struct MyType {
      MyType(MyType&amp;);  // no 'const'
  };
</code>

<p>and you try to aggregate it in a class that has a defaulted copy constructor with the usual signature:</p>
<code>
  template &lt;typename T&gt;
  struct Wrapper {
      Wrapper(const Wrapper&amp;) = default;
      T t;
  };
  
  Wrapper&lt;MyType&gt; var;  // fails to instantiate
</code>

<p>the resulting type is ill-formed, even if it is never used in a context where the copy constructor is required.</p>

<p>The authors believe this is unnecessarily restrictive; one should be able to use <code>Wrapper&lt;MyType&gt;</code> as 
long as one does not try to copy it.</p>

<p><code>std::tuple</code> is an example of a wrapper type which suffers from this problem in popular implementations.</p>

<h2><a name="Analysis"></a>Analysis</h2>

The relevant standard wording can be found in 11.4.2 [dcl.fct.def.default] paragraph 1 (emphasis ours):

<blockquote class="std">
  <ol>
    <li>[...] A function that is explicitly defaulted shall:
      <ul>
        <li>be a special member function,</li>
        <li>have the <strong>same declared function type</strong> (except for possibly differing ref-qualifiers and except that in
            the case of a copy constructor or copy assignment operator, the parameter type may be "reference to
            non-const T", where T is the name of the member function's class) <strong>as if it had been implicitly declared</strong>,
            and</li>
        <li>not have default arguments.</li>
      </ul>
    </li>
  </ol>
</blockquote>

<p>In the case of <code>Wrapper&lt;MyType&gt;</code>, the implicitly declared copy constructor would have the parameter type
<code>Wrapper&lt;MyType&gt;&amp;</code> per 15.8.1 [class.copy.ctor] paragraph 7, so an explicitly defaulted copy constructor with the
parameter type <code>const Wrapper&lt;MyType&gt;&amp;</code> is ill-formed.</p>

<h2><a name="Proposed_resolution"></a>Proposed Resolution</h2>

<p>This proposal suggests that if the declared type of an explicitly defaulted function is not the same as if it had been
implicitly declared, then it be defined as deleted, rather than being ill-formed.</p>

<h2><a name="Proposed_wording"></a>Proposed Wording</h2>

Change 11.4.2 [dcl.fct.def.default] paragraph 1 as indicated:

<blockquote class="std">
  <ol>
    <li>[...] A function that is explicitly defaulted shall:
      <ul>
        <li>be a special member function,<ins> and</ins></li>
        <li><del>have the same declared function type (except for possibly differing ref-qualifiers and except that in
            the case of a copy constructor or copy assignment operator, the parameter type may be "reference to
            non-const T", where T is the name of the member function's class) as if it had been implicitly declared,
            and</del></li>
        <li>not have default arguments.</li>
      </ul>
    </li>
  </ol>
</blockquote>

Add a new paragraph below 11.4.2 [dcl.fct.def.default] paragraph 1:

<blockquote class="std">
    <ins>The type of an explicitly defaulted function is allowed to differ from the type it would have if it were
         implicitly declared, as follows:</ins>
       <ul>
          <li><ins>it may have differing ref-qualifiers; and</ins></li>
          <li><ins>in the case of a copy constructor or copy assignment operator, the parameter type may be "reference 
              to non-const T", where T is the name of the member function's class.</ins></li>
       </ul>
        <ins>If the type differs in any other way, then:</ins>
       <ul>
        <li><ins>if the function is explicitly defaulted on its first declaration, it is defined as deleted;</ins></li>
        <li><ins>otherwise, the program is ill-formed.</ins></li>
       </ul>
</blockquote>

Delete 11.4.2 [dcl.fct.def.default] paragraph 3:

<blockquote class="std">
  <ol start="3">
    <li><del>If a function that is explicitly defaulted is declared with a <em>noexcept-specifier</em> that does not 
        produce the same exception specification as the implicit declaration ([except.spec]), then</del>
      <ul>
        <li><del>if the function is explicitly defaulted on its first declaration, it is defined as deleted;</del></li>
        <li><del>otherwise, the program is ill-formed.</del></li>
      </ul>
    </li>
  </ol>
</blockquote>

<h2><a name="Issues_resolved"></a>Issues Resolved</h2>

<p>This proposal would resolve Core Issues <a href="http://open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1331">#1331</a> 
and <a href="http://open-std.org/JTC1/SC22/WG21/docs/cwg_closed.html#1426">#1426</a>, both of which are in Extension status,
and are tracked by corresponding Evolution Issues <a href="http://cplusplus.github.io/EWG/ewg-active.html#101">#101</a> and
<a href="http://cplusplus.github.io/EWG/ewg-closed.html#103">#103</a>, respectively.</p>

</body></html>