<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2900: The copy and move constructors of optional are not constexpr</title>
<meta property="og:title" content="Issue 2900: The copy and move constructors of optional are not constexpr">
<meta property="og:description" content="C++ library issue. Status: C++17">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2900.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#C++17">C++17</a> status.</em></p>
<h3 id="2900"><a href="lwg-defects.html#2900">2900</a>. The copy and move constructors of <code>optional</code> are not <code>constexpr</code></h3>
<p><b>Section:</b> 22.5.3 <a href="https://wg21.link/optional.optional">[optional.optional]</a> <b>Status:</b> <a href="lwg-active.html#C++17">C++17</a>
 <b>Submitter:</b> United States <b>Opened:</b> 2017-02-03 <b>Last modified:</b> 2020-09-06</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#optional.optional">issues</a> in [optional.optional].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#C++17">C++17</a> status.</p>
<p><b>Discussion:</b></p>
<b>Addresses US 111</b>

<p>The copy and move constructors of <code>optional</code> are not <code>constexpr</code>. However, the constructors taking a 
<code>const T&amp;</code> or <code>T&amp;&amp;</code> are <code>constexpr</code>, and there is a precedent for having a <code>constexpr</code> 
copy constructor in 29.4.3 <a href="https://wg21.link/complex">[complex]</a>. The defaulted copy and move constructors of <code>pair</code> and <code>tuple</code> 
are also conditionally <code>constexpr</code> (see 20.4.2 [pairs.pair] p2 and 20.5.2.1 [tuple.cnstr] p2).</p>
<p>A strong motivating use-case is <code>constexpr</code> functions returning optional values. This issue was discovered while 
working on a library making heavy use of such.</p>

<p>Proposed change: Add constexpr to: </p>
<blockquote><pre>
optional(const optional &amp;);
optional(optional &amp;&amp;) noexcept(<i>see below</i>);
</pre></blockquote>

<p><i>[2017-02-23, Casey comments and suggests wording]</i></p>

<p>
This issue corresponds to NB comment US 111, which requests that the move and copy constructors of 
<code>std::optional</code> be declared <code>constexpr</code>. The PR simply suggests adding the <code>constexpr</code> 
specifier to the declarations of the constructors. The PR fails to specify the most important thing &mdash; 
and this has been a failing of Library in general &mdash; under what conditions is the thing that we've 
declared constexpr actually expected to be usable in constant expression context? (I think the proper 
standardese here is "under what conditions is the full expression of an initialization that would invoke 
these constructors a constant subexpression?")
<p/>
It is, I believe, well-known that conforming implementations of <code>optional&lt;T&gt;</code> must store a <code>T</code> 
in a union to provide constexpr constructors that either do [<code>optional(T const&amp;)</code>] or do not 
[<code>optional()</code>] initialize the contained <code>T</code>. A general implementation of <code>optional</code>'s 
copy/move constructors must statically choose which union member, if any, to activate in each constructor. 
Since there is no way to change the active member of a union in a constant expression, and a constructor must 
<em>statically</em> choose a union member to activate (i.e., without being affected by the runtime state of the 
copy/move constructor's argument) it's not possible to implement a <em>general</em> constexpr copy/move constructor 
for <code>optional</code>.
<p/>
It is, however, possible to copy/move construct a trivially copy constructible/trivially move constructible union 
in <code>constexpr</code> context, which effectively copies the union's object representation, resulting in a union 
whose active member is the same as the source union's. Indeed, at least two major implementations of <code>optional</code> 
(MSVC and libc++) already provide that behavior as a conforming optimization when <code>T</code> is a trivially 
copyable type. If we are to declare <code>optional&lt;T&gt;</code>'s copy and move constructors <code>constexpr</code>, 
we should additionally specify that those constructors are only required to have the "constexpr mojo" when <code>T</code> 
is trivially copyable. (Note that I suggest "trivially copyable" here rather than "trivially copy constructible or 
trivially move constructible" since the simpler requirement is simpler to implement, and I don't believe the more 
complicated requirement provides any additional benefit: I've never seen a trivially copy constructible or 
trivially move constructible type outside of a test suite that was not also trivially copyable.)
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
<p>This wording is relative to <a href="https://wg21.link/N4618">N4618</a>.</p>
<ol>
<li><p>Edit 22.5.3 <a href="https://wg21.link/optional.optional">[optional.optional]</a> as indicated:</p>
<blockquote><pre>
	<code><ins>constexpr</ins> optional(const optional &amp;);</code>
	<code><ins>constexpr</ins> optional(optional &amp;&amp;) noexcept(<i>see below</i>);</code>
</pre></blockquote>
</li>

<li><p>Edit 22.5.3.2 <a href="https://wg21.link/optional.ctor">[optional.ctor]</a> paragraph as indicated:</p>
<blockquote><pre>
	<code><ins>constexpr</ins> optional(const optional &amp;);</code>
</pre></blockquote>

<p>and </p>

<blockquote><pre>
	<code><ins>constexpr</ins> optional(optional &amp;&amp;) noexcept(<i>see below</i>);</code>
</pre></blockquote>
</li>
</ol>
</blockquote>

<p><i>[2017-02-23, Marshall comments]</i></p>

<p>
This is related to LWG <a href="lwg-defects.html#2745" title="[fund.ts.v2] Implementability of LWG 2451 (Status: TS)">2745</a><sup><a href="https://cplusplus.github.io/LWG/issue2745" title="Latest snapshot">(i)</a></sup>.
</p>

<p><i>[2017-02-28, Kona, Casey comments and improves wording]</i></p>

<p>
Amended PR per LWG discussion in Kona: replace the "is trivially copyable" requirement with the more specific 
<code>is_trivially_copy/move_constructible&lt;T&gt;</code>. LWG was concerned that <code>tuple</code> is a counter-example 
to the assumption that all three traits are equivalent for real-world types.
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
<p>
This wording is relative to <a href="https://wg21.link/n4640">N4640</a>.
</p>

<ol>
<li><p>Change the synopsis of class template <code>optional</code> in 22.5.3 <a href="https://wg21.link/optional.optional">[optional.optional]</a> as follows:</p>

<blockquote><pre>
[&hellip;]
// 20.6.3.1, constructors
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
<ins>constexpr</ins> optional(const optional&amp;);
<ins>constexpr</ins> optional(optional&amp;&amp;) noexcept(<i>see below</i>);
[&hellip;]
</pre></blockquote>
</li>

<li><p>Modify 22.5.3.2 <a href="https://wg21.link/optional.ctor">[optional.ctor]</a> as indicated:</p>
<blockquote><pre>
<ins>constexpr</ins> optional(const optional&amp; rhs);
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-6- <i>Remarks:</i> This constructor shall be defined as deleted unless <code>is_copy_constructible_v&lt;T&gt;</code> 
is <code>true</code>. <ins>If <code>T</code> is a trivially copyable type, this constructor shall be a <code>constexpr</code> constructor.</ins>
</p>
</blockquote>
<pre>
<ins>constexpr</ins> optional(optional&amp;&amp; rhs) noexcept(<i>see below</i>);
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-10- <i>Remarks:</i> The expression inside <code>noexcept</code> is equivalent to <code>is_nothrow_move_constructible_v&lt;T&gt;</code>.
This constructor shall not participate in overload resolution unless <code>is_move_constructible_v&lt;T&gt;</code> is
<code>true</code>. <ins>If <code>T</code> is a trivially copyable type, this constructor shall be a <code>constexpr</code> constructor.</ins>
</p>
</blockquote>
</blockquote>
</li>
</ol>

</blockquote>
<p><i>[Kona 2017-02-27]</i></p>

<p>Accepted as Immediate to resolve NB comment.</p>


<p id="res-2900"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4640">N4640</a>.
</p>

<ol>
<li><p>Change the synopsis of class template <code>optional</code> in 22.5.3 <a href="https://wg21.link/optional.optional">[optional.optional]</a> as follows:</p>

<blockquote><pre>
[&hellip;]
// 20.6.3.1, constructors
constexpr optional() noexcept;
constexpr optional(nullopt_t) noexcept;
<ins>constexpr</ins> optional(const optional&amp;);
<ins>constexpr</ins> optional(optional&amp;&amp;) noexcept(<i>see below</i>);
[&hellip;]
</pre></blockquote>
</li>

<li><p>Modify 22.5.3.2 <a href="https://wg21.link/optional.ctor">[optional.ctor]</a> as indicated:</p>
<blockquote><pre>
<ins>constexpr</ins> optional(const optional&amp; rhs);
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-6- <i>Remarks:</i> This constructor shall be defined as deleted unless <code>is_copy_constructible_v&lt;T&gt;</code> 
is <code>true</code>. <ins>If <code>is_trivially_copy_constructible_v&lt;T&gt;</code> is <code>true</code>, this constructor 
shall be a <code>constexpr</code> constructor.</ins>
</p>
</blockquote>
<pre>
<ins>constexpr</ins> optional(optional&amp;&amp; rhs) noexcept(<i>see below</i>);
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-10- <i>Remarks:</i> The expression inside <code>noexcept</code> is equivalent to <code>is_nothrow_move_constructible_v&lt;T&gt;</code>.
This constructor shall not participate in overload resolution unless <code>is_move_constructible_v&lt;T&gt;</code> is
<code>true</code>. <ins>If <code>is_trivially_move_constructible_v&lt;T&gt;</code> is <code>true</code>, this constructor shall 
be a <code>constexpr</code> constructor.</ins>
</p>
</blockquote>
</blockquote>
</li>
</ol>








</body>
</html>
