<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 2753: Optional's constructors and assignments need constraints</title>
<meta property="og:title" content="Issue 2753: Optional's constructors and assignments need constraints">
<meta property="og:description" content="C++ library issue. Status: Resolved">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue2753.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#Resolved">Resolved</a> status.</em></p>
<h3 id="2753"><a href="lwg-defects.html#2753">2753</a>. Optional's constructors and assignments need constraints</h3>
<p><b>Section:</b> 22.5.3.2 <a href="https://wg21.link/optional.ctor">[optional.ctor]</a>, 22.5.3.4 <a href="https://wg21.link/optional.assign">[optional.assign]</a> <b>Status:</b> <a href="lwg-active.html#Resolved">Resolved</a>
 <b>Submitter:</b> Casey Carter <b>Opened:</b> 2016-07-22 <b>Last modified:</b> 2017-06-15</p>
<p><b>Priority: </b>0
</p>
<p><b>View all other</b> <a href="lwg-index.html#optional.ctor">issues</a> in [optional.ctor].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Resolved">Resolved</a> status.</p>
<p><b>Discussion:</b></p>
<p>
To use <code>optional&lt;T&gt;</code> as if it were a <code>T</code> in generic contexts, <code>optional&lt;T&gt;</code>'s "generic" 
operations must behave as do those of <code>T</code> under overload resolution. At minimum, <code>optional</code>'s constructors 
and assignment operators should not participate in overload resolution with argument types that cannot be used to 
construct/assign the contained <code>T</code> so that <code>is_constructible_v&lt;optional&lt;T&gt;, Args...&gt;</code> 
(respectively <code>is_assignable_v&lt;optional&lt;T&gt;&amp;, RHS&gt;</code>) is equivalent to 
<code>is_constructible_v&lt;T, Args...&gt;</code> (respectively <code>is_assignable_v&lt;T&amp;, RHS&gt;</code>).
</p>
<p>
In passing, note that the Requires element for <code>optional</code>'s in-place <code>initializer_list</code> constructor 
unnecessarily duplicates its Remarks element; it should be removed.
</p>
<p>
It should also be noted that the resolution of LWG <a href="lwg-defects.html#2451" title="[fund.ts.v2] optional&lt;T&gt; should 'forward' T's implicit conversions (Status: TS)">2451</a><sup><a href="https://cplusplus.github.io/LWG/issue2451" title="Latest snapshot">(i)</a></sup> adds constructors to <code>optional</code> with 
appropriate constraints, but does not constrain the additional assignment operators. If LWG chooses to apply the 
resolution of 2451 to the WP, the Requires elements of the additional assignment operators should also be converted 
to constraints as the wording herein does for the assignment operators in N4606.
</p>
<p><i>[2016-07 Chicago]</i></p>

<p>Monday: P0 - tentatively ready</p>

<p><i>[2016-11-28 Post-Issaquah]</i></p>

<p>Resolved by the adoption of <a href="lwg-defects.html#2756" title="C++ WP optional&lt;T&gt; should 'forward' T's implicit conversions (Status: C++17)">2756</a><sup><a href="https://cplusplus.github.io/LWG/issue2756" title="Latest snapshot">(i)</a></sup></p>


<p id="res-2753"><b>Proposed resolution:</b></p>
<p>This wording is relative to N4606.</p>

<ol>
<li><p>Remove  [optional.object.ctor] p3, and add a new paragraph after p6:</p>

<blockquote>
<pre>
optional(const optional&lt;T&gt;&amp; rhs);
</pre>
<blockquote>
<p>
<del>-3- <i>Requires:</i> <code>is_copy_constructible_v&lt;T&gt;</code> is <code>true</code>.</del>
<p/>
[&hellip;]
<p/>
<ins>-?- <em>Remarks:</em> The function shall not participate in overload resolution unless 
<code>is_copy_constructible_v&lt;T&gt;</code> is <code>true</code>.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Remove  [optional.object.ctor] p7, and change p11 to:</p>

<blockquote>
<pre>
optional(optional&lt;T&gt;&amp;&amp; rhs) noexcept(<i>see below</i>);
</pre>
<blockquote>
<p>
<del>-7- <i>Requires:</i> <code>is_move_constructible_v&lt;T&gt;</code> is <code>true</code>.</del>
<p/>
[&hellip;]
<p/>
-11- <em>Remarks:</em> The expression inside <code>noexcept</code> is equivalent to 
<code>is_nothrow_move_constructible_v&lt;T&gt;</code>. <ins>The function shall not participate in 
overload resolution unless <code>is_move_constructible_v&lt;T&gt;</code> is <code>true</code>.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Remove  [optional.object.ctor] p12, and change p16 to:</p>

<blockquote>
<pre>
constexpr optional(const T&amp; v);
</pre>
<blockquote>
<p>
<del>-12- <i>Requires:</i> <code>is_copy_constructible_v&lt;T&gt;</code> is <code>true</code>.</del>
<p/>
[&hellip;]
<p/>
-16- <em>Remarks:</em> If <code>T</code>'s selected constructor is a <code>constexpr</code> constructor, 
this constructor shall be a <code>constexpr</code> constructor. <ins>The function shall not participate 
in overload resolution unless <code>is_copy_constructible_v&lt;T&gt;</code> is <code>true</code>.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Remove  [optional.object.ctor] p17, and change p21 to:</p>

<blockquote>
<pre>
constexpr optional(T&amp;&amp; v);
</pre>
<blockquote>
<p>
<del>-17- <i>Requires:</i> <code>is_move_constructible_v&lt;T&gt;</code> is <code>true</code>.</del>
<p/>
[&hellip;]
<p/>
-21- <em>Remarks:</em> If <code>T</code>'s selected constructor is a <code>constexpr</code> constructor, this constructor shall 
be a <code>constexpr</code> constructor. <ins>The function shall not participate in overload resolution unless 
<code>is_move_constructible_v&lt;T&gt;</code> is <code>true</code>.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Remove  [optional.object.ctor] p22, and change p26 to:</p>

<blockquote>
<pre>
template &lt;class... Args&gt; 
  constexpr explicit optional(in_place_t, Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
<del>-22- <i>Requires:</i> <code>is_constructible_v&lt;T, Args&amp;&amp;...&gt;</code> is <code>true</code>.</del>
<p/>
[&hellip;]
<p/>
-26- <em>Remarks:</em> If <code>T</code>'s constructor selected for the initialization is a <code>constexpr</code> constructor, 
this constructor shall be a <code>constexpr</code> constructor. <ins>The function shall not participate in overload 
resolution unless <code>is_constructible_v&lt;T, Args...&gt;</code> is <code>true</code>.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Remove  [optional.object.ctor] p27.</p>

<blockquote>
<pre>
template &lt;class U, class... Args&gt; 
  constexpr explicit optional(in_place_t, initializer_list&lt;U&gt; il, Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
<del>-27- <i>Requires:</i> <code>is_constructible_v&lt;T, initializer_list&lt;U&gt;&amp;, Args&amp;&amp;...&gt;</code> is 
<code>true</code>.</del>
<p/>
[&hellip;]
</p>
</blockquote>
</blockquote>
</li>

<li><p>Remove  [optional.object.assign] p4, and change p8 to:</p>

<blockquote>
<pre>
optional&lt;T&gt;&amp; operator=(const optional&lt;T&gt;&amp; rhs);
</pre>
<blockquote>
<p>
<del>-4- <i>Requires:</i> <code>is_copy_constructible_v&lt;T&gt;</code> is <code>true</code> and 
<code>is_copy_assignable_v&lt;T&gt;</code> is <code>true</code>.</del>
<p/>
[&hellip;]
<p/>
-8- <em>Remarks:</em> If any exception is thrown, the result of the expression <code>bool(*this)</code> remains unchanged. 
If an exception is thrown during the call to <code>T</code>'s copy constructor, no effect. If an exception is thrown 
during the call to <code>T</code>'s copy assignment, the state of its contained value is as defined by the exception 
safety guarantee of <code>T</code>'s copy assignment. <ins>The function shall not participate in overload resolution 
unless <code>is_copy_constructible_v&lt;T&gt; &amp;&amp; is_copy_assignable_v&lt;T&gt;</code> is <code>true</code>.</ins>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Remove  [optional.object.assign] p9, and add a new paragraph after p14:</p>

<blockquote>
<pre>
optional&lt;T&gt;&amp; operator=(optional&lt;T&gt;&amp;&amp; rhs) noexcept(<i>see below</i>);
</pre>
<blockquote>
<p>
<del>-9- <i>Requires:</i> <code>is_move_constructible_v&lt;T&gt;</code> is <code>true</code> and 
<code>is_move_assignable_v&lt;T&gt;</code> is <code>true</code>.</del>
<p/>
[&hellip;]
<p/>
-14- <i>Remarks:</i> [&hellip;] If an exception is thrown during the call to <code>T</code>'s move
assignment, the state of <code>*val</code> and <code>*rhs.val</code> is determined by the exception safety 
guarantee of <code>T</code>'s move assignment.
<p/>
<ins>The function shall not participate in overload resolution unless 
<code>is_move_constructible_v&lt;T&gt; &amp;&amp; is_move_assignable_v&lt;T&gt;</code> is <code>true</code>.</ins></p>
</blockquote>
</blockquote>
</li>

<li><p>Remove  [optional.object.assign] p15, and change p19 to (yes, this wording is odd - the intent 
is that it will "do the right thing" after incorporation of LWG <a href="lwg-defects.html#2451" title="[fund.ts.v2] optional&lt;T&gt; should 'forward' T's implicit conversions (Status: TS)">2451</a><sup><a href="https://cplusplus.github.io/LWG/issue2451" title="Latest snapshot">(i)</a></sup>):</p>

<blockquote>
<pre>
template &lt;class U&gt; optional&lt;T&gt;&amp; operator=(U&amp;&amp; v);
</pre>
<blockquote>
<p>
<del>-15- <i>Requires:</i> <code>is_constructible_v&lt;T, U&gt;</code> is <code>true</code> and 
<code>is_assignable_v&lt;T&amp;, U&gt;</code> is <code>true</code>.</del>
<p/>
[&hellip;]
<p/>
-19- <em>Remarks:</em> If any exception is thrown, the result of the expression <code>bool(*this)</code> remains unchanged. 
If an exception is thrown during the call to <code>T</code>'s constructor, the state of <code>v</code> is determined by the 
exception safety guarantee of <code>T</code>'s constructor. If an exception is thrown during the call to <code>T</code>'s 
assignment, the state of <code>*val</code> and <code>v</code> is determined by the exception safety guarantee of <code>T</code>'s 
assignment. The function shall not participate in overload resolution unless <code>is_same_v&lt;decay_t&lt;U&gt;, 
T&gt;<ins> &amp;&amp; is_constructible_v&lt;T, U&gt; &amp;&amp; is_assignable_v&lt;T&amp;, U&gt;</ins></code> is 
<code>true</code>.
</p>
</blockquote>
</blockquote>
</li>
</ol>





</body>
</html>
