<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
        "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
	<title>An allocator-aware optional type</title>

	<style>
	p {text-align:justify}
	li {text-align:justify}
	blockquote.note
	{
		background-color:#E0E0E0;
		padding-left: 15px;
		padding-right: 15px;
		padding-top: 1px;
		padding-bottom: 1px;
	}
	tab { padding-left: 2em; }
    tab2 { padding-left: 4em; }
	ins {background-color:#A0FFA0}
	del {background-color:#FFA0A0}
	</style>
</head>
<body>

<address align=right>
Document number: P2047R3
<br/>
Audience: LEWG
<br/>
<br/>
<a href="mailto:ville.voutilainen@gmail.com">Ville Voutilainen</a><br/>
<a href="mailto:dinka.ranns@gmail.com">Nina Dinka Ranns</a><br/>
<a href="mailto:phalpern@halpernwightsoftware.com">Pablo Halpern</a><br/>
2022-07-06<br/>
</address>
<hr/>
<h1 align=center>An allocator-aware optional type</h1>

<h2>Abstract</h2>
 
<p>
  Library types that can potentially hold <em>allocator-aware (AA)</em>
  objects should, themselves, be allocator-aware. A PMR container, for example,
  depends on AA types following a known AA protocol so that it (the container)
  can uniformly manage its memory. Even types that don't manage their own
  memory, such as <tt>tuple</tt>, follow the AA rules when they hold one more
  more AA elements. (A special case is <tt>pair</tt>, which is not actually AA
  but effectively follows the rules through special handling
  in <em>uses-allocator construction</em>.)
</p>
<p>
  The current definition of <tt>std::optional</tt> does not follow the rules
  for an AA type, even when holding an AA value. This limitation
  makes <tt>std::optional</tt> unsuitable for storage in an AA container when
  memory allocation customization is needed.
</p>
<p>
  In this paper, we propose a new, allocator-aware
  <tt>std::pmr::optional</tt> usable as a container element type and in any
  other context where allocator propagation is expected. This new type would
  not replace the current <tt>std::optional</tt>, but would resolve to
  <tt>std::optional</tt> when the value type is not AA. By automatically
  handling the distinction between AA and non-AA value types,
  <tt>std::pmr::optional</tt> can easily be used in generic code where it is not
  known in advance if it would be storing an AA type or not.
</p>
<p>  
  This is a complete proposal with formal wording.
  It has not yet been discussed in LEWGI or LEWG.
</p>

<p>
<br/>change history :
<br/>- replaced <tt>alloc_optional</tt> with additional overloads of <tt>make_optional</tt> that
take an <tt>allocator_arg_t</tt> : it was observed that <tt>alloc_optional</tt> doesn't actually
do any allocation, and that the name is not appropriate
<br/>- fixed the order of arguments in the <i>Returns</i> clause of what used to be <tt>alloc_optional</tt>
<br/>- adjusted for LWG 2833
<br/>- added discussion on deduction guides
<br/>- removed mentions of using a type alias since the type alias approach has proven to be problematic
<br/>- modified the specification of std::pmr::optional to cover both AA and non AA types
<br/>- added CTAD specification
<br/>- modified the specification of <tt>std::pmr::optional</tt> to be expressed in terms of 
	<tt>std::pmr::polymorphic_allocator&lt;&gt;</tt>, as opposed to <tt>std::pmr::memory_resource</tt>
</p>
<br/>- moved <tt>std::pmr::optional</tt> to <tt>optional</tt> header as discussed in the reflector discussion
<br/>- added request for discussion on making <tt>std::pmr::optional</tt> a more allocator generic type.
<br/>- added free swap function to be in line with P0178 
<br/>R3:
<br/>- replaced instances of <i>M_alloc</i> with <i>alloc</i>
<br/>- clarified pmr::optional constructor descriptions to call out uses-allocator construction
<br/>- expanded <tt>basic_optional</tt> discussion
 
<h2>Motivation and Proposal Summary</h2>
<p>
  C++ has been moving towards a consistent PMR allocator model whereby
  <em>allocator-aware (AA)</em> types adhere to a few rules:
</p>
<ol>
  <li>Once constructed, an object's allocator never changes.</li>
  <li>The object's constructors all follow one of two argument protocols so
    that they work with <em>uses-allocator construction</em> and thus can be
    inserted as container elements using the container's allocator.</li>
  <li>An object that can contain an AA element of user-specified type should
    itself be AA and use its allocator to initialize its AA subobjects.</li>
</ol>

<p>
  The current <tt>std::optional</tt> does not follow the above rules. When
  disengaged, it forgets its allocator, violating the first rule; its
  constructors don't follow the AA protocols, so containers cannot pass their
  allocators to <tt>optional</tt> elements; and it does not hold on an
  allocator by which it can initialize it's contained object. As a
  result, <tt>std::optional</tt> is not a good fit for situations where
  allocators are used.
  A <tt>std::pmr::vector&lt;optional&lt;std::pmr::string&gt;&gt;</tt>, for example,
  cannot ensure that all of strings within it use the same allocator,
  violating a key invariant of PMR containers. If one of the elements of the
  vector became disengaged and re-engaged, for example, the allocator for that
  one element could change.
</p>
<p>
  The <tt>std::pmr::optional</tt> class template proposed here properly adheres to
  the rules of an AA type when instantiated with an AA value type. It holds a
  copy of the allocator used to construct it, even when disengaged, and uses
  that allocator to construct its element when re-engaged. Containers
  of <tt>std::pmr::optional</tt> objects can correctly manage their memory.
</p>

<p>
  The basic design of an AA optional is straight-forward: Add an allocator to
  all of its constructors and use that allocator to construct the value object
  each type the optional is engaged.  However, when holding a non-AA type,
  there is no reason to pay the overhead of storing an allocator, nor to
  support the AA constructor interface. For this
  reason, <tt>std::pmr::optional</tt> has a different specialisation for AA and
  non-AAtype. 
 </p>

<h2>Design decisions:</h2>
<p>
  Rather than support the entire set of allocator types allowed for C++20 containers
  allocators, <tt>std::pmr::optional</tt> works only
  with <tt>std::pmr::polymorphic_allocator</tt>. The design keeps the allocator
  from infecting the optional's type, in the sense that it's not a template
  parameter. The modern PMR-style allocator model simplifies specification,
  implementation, and use of <tt>std::pmr::optional</tt>.  Allocator-aware
  optionals are interoperable even if they use different concrete allocators,
  because the concrete allocator doesn't change the type, nor does it change
  the size of the type.
</p>

<!--  <p>
  When prototyping this proposal, we realized that an allocator-aware
  optional is never trivially copyable. Copy construction and copy
  assignment always potentially invoke the allocator; these operations
  are never bitwise copies. Move operations aren't trivial either, because
  they may also end up doing uses-allocator construction.
</p> -->
  
<p>
	An early draft of this proposal suggested using a type alias where a non-AA <tt>std::pmr::optional</tt>
	aliases <tt>std::optional</tt>, and AA <tt>std::pmr::optional</tt> aliases a new unnamed type. 
  However, this causes usability issues. Type deduction in cases like :
<br/><tt>
<br/>template &lt;typename T&gt;
<br/>void foo(std::pmr::optional&lt;T&gt;);
<br/></tt>

<br/>did not work. The above was equivalent to 

<br/><tt>
<br/>template &lttypename T&gt
<br/>void foo(std::conditional&lt;std::uses_allocator &lt;T, std::pmr::polymorphic_allocator&lt;&gt;&gt;::value ,
<br/><tab2/><tab2/><tab2/><i>alloc_optional</i>&ltT&gt,
<br/><tab2/><tab2/><tab2/>std::optional&lt;T&gt;&gt;:type);
<br/></tt>
<br/> 
and using the nested <tt>type</tt> of the <tt>std::condigit logtional</tt> as the function template parameter  made for an undeduced context.
</p>
  
<br/>The free swap function has been made to have a wide contract and work with different allocators, as discussed in 
P0178 (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0178r0.html)

<h2>Feedback items for LEWG: </h2>

<p><h3>Should <tt>std::pmr::optional</tt> be a more allocator generic type ? </h3></p>
<p>
  In the reflector discussion, Ville Voutilainen and Tomasz Kamińskimasz made the following request : ": The C++ standard library should 
  provide building blocks that allow multiple semantics to be expressed, as opposed to deciding on a narrow subset, 
  and making an allocator-aware optional obey the static properties, namely the propagation traits, of an allocator is a fundamental piece of such genericity.
  See P2080 https://wg21.link/P2080"
  
</p>
<p>
<br/>  
  This approach would consist of a basic_optional type :
<br/>
<br/>  <tt> template &lt;class T, class Alloc&gt
<br/>       basic_optional&lt;T, Alloc&gt;</tt>  
<br/> 
<br/>Furthermore, <tt>pmr::optional&lt;T&gt;</tt> would be <tt>basic_optional&lt;T, std::pmr::polymorphic_allocator&lt;&gt;&gt;</tt>
</p>
<p>
<br/> Such <tt>basic_optional</tt> would be "allocator aware" even for types that use an allocator other than <tt>std::pmr::polymorphic_allocator</tt>.
 Users of allocators with different propagation traits to <tt>std::pmr::polymorphic_allocator</tt> would not be required to write their own
 allocator aware optional implementations as basic_optional would respect the propagation traits of the allocator used, and could be used
 with allocator aware containers like vector "out of the box". These users are not theoretical. In his feedback, Ville Voutilainen writes :
<br/>
<br/><tab/> <i>"I have resource-constrained (read "embedded" if you like) scenarios where I
need to specify a memory arena that a particular software component uses. All
allocator-aware things in that component need
to use the same arena, and it's much preferred if the same arena is
used by default, instead of having to specify it
explicity as an exception to the default. For that to happen, SOCCC
needs to return the same allocator, not create
a fresh new one, and POCMA needs to be true. I can't solve this with a
per-thread default resource, there are multiple
separate components running on the same thread, using separate memory arenas.

Our pmr::memory_resource works fine for such scenarios. Our
std::polymorphic_allocator does not. Our containers
work fine, because they obey the propagation traits. New facilities
don't work in such scenarios if they don't support
propagation traits that are different from the ones of
std::polymorphic_allocator." </i>
  
</p>
<p>
One could argue that it makes no sense for such a propagating allocator to be a scoped allocator and vice versa.  
Scoped allocators exist for the purpose of ensuring consistency between a container and its contained elements' allocator.  
A propagating allocator is used in exactly those situations where such consistency is not required and might be undesirable. 
 Consider the vector case with a propagating, non-scoped allocator:
<br/>
<br/>
<tt>template &lt;class T&gt;
<br/>class PropAlloc
<br/>{
<br/><tab/>  public:
<br/><tab/>    ...
<br/><tab/>    using propagate_on_container_copy_assignment = std::true_type;
<br/><tab/>    using propagate_on_container_move_assignment = std::true_type;
<br/><tab/>    using propagate_on_container_swap            = std::true_type;
<br/>};
<br/>
<br/>using MyString = std::string&lt;char, std::char_traits&lt;char&gt;, PropAlloc&lt;char&gt;&gt;;
<br/>using MyVector = std::vector&lt;MyString, PropAlloc&lt;MyString&gt;&gt;;
<br/>
<br/>PropAlloc allocA(1);
<br/>PropAlloc allocB(2);
<br/>
<br/>MyVector v(allocA);
<br/>v.push_back("hello");
<br/>v[0] = MyString("goodbye", allocB);
<br/>assert(allocA == v.get_allocator());
<br/>assert(allocB == v[0].get_allocator());
</tt>
<br/>
<br/>Note that, by design, the vector and its elements do not share an allocator.  
There is nothing wrong with that, but it is not the scoped allocator model.  Now, let's do the same with optional:
<br/>
<tt>
<br/>using MyOptional = std::basic_optional&lt;MyString, PropAlloc&lt;char&gt;&gt;;
<br/>MyOptional opt(std::allocator_arg_t, allocA, MyString("hello"));
<br/>opt = MyString("goodbye", allocB);
<br/>assert(allocA == opt.get_allocator());
<br/>assert(allocB == opt.value().get_allocator());
</tt>
<br/>
<br/>
The behavior mimics the vector case, so what's the problem?  
The problem is "what's the purpose of storing an allocator in optional in the first place?"  
For vector, the allocator is used by the vector itself to allocate memory.  
For optional, however, the optional object does not allocate memory, so has no use for an allocator.  
It stores it for use by the value object, but if the value object's allocator 
isn't consistent with the optional, then it seems to have no real purpose.  
Instead, the allocator for the value can be passed directly into the emplace functions,
using the existing mechanisms. However, one can conceive a scoped allocator 
that is not polymorphic and might even use fancy pointer types. 
Having `basic_optional` does give flexibility to support that.
</p>

<p> Such approach adds some complexity to the design and reasoning about what happens. 
Consider:
<br/>
<tt>
<br/>basic_optional&lt;T, AllocA &gt; alice;
<br/>basic_optional&lt;U, AllocB &gt; bob = alice; // #1
<br/>alice = bob // #2</tt>
<br/> 
<br/>The questions that need to be answered are
<br/>1)  what requirements are needed from AllocA and AllocB for #1 and #2 to be valid ?
<br/>2)  what is the resulting allocator ?     
<br/>
<br/> One possible approach is to disallow #1 and #2 unless AllocA and AllocB are 
different specialisations of the same allocator. The user can still achieve construction/assignment 
by retrieving the underlying value type object :
<br/>
 <tt>
<br/>basic_optional&lt;T, AllocA &gt; alice;
<br/>basic_optional&lt;U, AllocB &gt; bob = alice.value(); 
<br/>alice = bob.value() </tt>
<br/>
<br/>It's worth noting that this approach increases 
the number of constructors and assignment operators.

<br/> 
<br/> With the approach described above, the resulting allocator is determined by the 
<tt>allocator_traits&lt;AllocB&gt;</tt> which are the same as <tt>allocator_traits&lt;AllocA&gt;</tt>.
To ensure this is the case, and to keep the value_type allocator in sync with the basic_optiona allocator, 
every operation which would modify the allocator according to 
the <tt>allocator_traits&lt;AllocB&gt;</tt> needs to be implemented in terms of uses-allocator construction.
<br/>
<br/> Now consider :
<br/>
<tt><br/>alice = basic_optional&lt;T, AllocA &gt;{} </tt>
<br/>
<br/> When <tt>allocator_traits&lt;AllocA &gt;::propagate_on_container_move_assignment::value == true</tt>,
<tt>allocator_traits&lt;AllocA &gt;::propagate_on_container_copy_assignment::value == false</tt>, 
and <tt>T</tt> does not support move semantics, we get into a situation where an assignment through optional
object propagates the allocator, while the same assignment to a naked value_type objects doesn't. If the user
designed the type (i.e. deliberately disabled move semantics) with the intention that the allocator never 
changes after the object has been constructed, this could cause a problem. We are not aware of such users, but
the case is presented for the purposes of documenting that it has been considered.
</p>
<p> The issues discussed above are avoided in the current design because allocator traits of <tt>std::pmr::polymorphic_allocator&lt;&gt;</tt>
do not allow for allocator to change after the object has been created. Similarly, because only one allocator family is supported, there is no need
to consider cases where the rhs allocator is of an unrelated type. However, the application of the current design is limited to a 
subset of users of allocator aware standard containers. 
Users who need allocators with propagation traits that are different to that of <tt>std::pmr::polymorphic_allocator&lt;&gt;</tt>
would still need to write their own alllocator aware optional. If we can express the semantics of the current design 
in terms of the propagation traits of std::polymorphic_allocator, then we can easily extend the design to cover 
other propagation traits. The remaining work is deciding what to do with allocators that are unrelated and
perhaps even non-convertible. For such questions, there's an approach that's forward-compatible and allows 
relaxations/extensions in the future.
</p>

If we decide to pursue basic_optional, we need to decide whether we want to support non-scoped propagating allocators. 
That is, should the construction of the value_type element be done using uses-allocator construction or directly 
through <tt>allocator_traits&lt;alloc&gt;::construct()</tt>. 

	<h3>Should <tt>std::pmr::optional</tt> be placed in the <tt>&lt;optional&gt;</tt> header?
</h3>
	<br/> This proposal puts <tt>std::pmr::optional</tt> in a <tt>optional</tt> header. Historically, pmr containers didn't have their own header files.
	However, <tt>std::pmr::optional</tt> is a more complex type than, for example, <tt>std::pmr::vector</tt>.
	<br/>
<h3>Should the deduction guide for mixed optional unpack or not?</p>
</h3>
<p>
Consider
<tt>
<br/>
<br/>  std::optional x1 = value_type();
<br/>  std::pmr::optional copy1 = x1; // #1
<br/>
<br/>  std::optional x2 = value_type_aa();
<br/>  std::pmr::optional copy2 = x2; // #2
<br/>
<br/>  std::pmr::optional x3 = value_type();
<br/>  std::optional copy3 = x3; // #3
<br/>
<br/>  std::pmr::optional x4 = value_type_aa();
<br/>  std::optional copy4 = x4; // #4
</tt>
<br/>
<br/>What should the types of <tt>x1</tt>, <tt>x2</tt>, <tt>x3</tt>, and <tt>x4</tt>
in the above example be ? 
<br/>
<br/>The current proposal favours unpacking, and the types are <tt>std::pmr::optional&lt;value_type&gt;</tt>
,  <tt>std::pmr::optional&lt;value_type_aa&gt;</tt>,  <tt>std::optional&lt;value_type&gt;</tt>
and  <tt>std::optional&lt;value_type_aa&gt;</tt>. This seems to fit with the idea that
	<tt>std::pmr::optional</tt> and <tt>std::optional</tt> are types that are close enough that they deserve to be
treated equally wherever they can. However, it does mean that they are somehow blessed
by the standard to work together in a way a user defined type which inherits from <tt>std::optional</tt>
wouldn't be. 
</p>


<p><h3> Which allocator should be used in value_or ?</p></h3>
<p>
  It is not all that obvious which allocator should be used for the
	object returned by <tt>value_or</tt>. Should the decision be left to the type
  or should it be mandated by the optional ? That is, should the object
  be constructed by plain copy/move construction or with uses-allocator 
  construction?
  
</p>
<p><h3> Should assignments use <t>is_­constructible</t> trait ? </h3> </p>
<p>It's not construct from U we need, it's construct from U using the allocator. Do we need a new trait ?</p>

<p><h3>Do we need an “allocator_aware” concept?</h3></p>
<p>
  We might consider an “allocator aware” (AA) concept that requires
  a <tt>get_allocator()</tt>
  method that returns something convertible to <tt>std::pmr::polymorphic_allocator&lt;&gt;</tt>.
  If we used this concept instead of the <tt>std::uses_allocator</tt> trait, the allocator would require
  zero extra space in most (but not all) cases. (The exception would be a type that stores 
  its allocator outside of its footprint and whose footprint is smaller than 
  polymorphic_allocator<>.)
</p>




<h2>Proposed wording</h2>
<p>
Add new paragraphs after 20.6.1/p1 [optional.general]
</p>
<p> <blockquote>
<ins>
[2] <tt>pmr::optional</tt> is a class template such that for a type <tt>T</tt>, where
<tt>uses_allocator&lt;T, pmr::polymorphic_allocator&lt;&gt;&gt;</tt> is true, an optional object of type 
<tt>pmr::optional&lt;T&gt;</tt> will construct the contained object, if any,
	with an allocator of type <tt>pmr::polymorphic_allocator&lt;&gt;</tt>. 
<br/>


<p>Modify 20.6.2 Header <optional> synopsisl [optional.syn] </p>
<p>
<blockquote>
<tt>
<br/>namespace std {
<br/><tab/> // [optional.optional], class template optional
<br/><tab/> template&lt;class T&gt;
<br/><tab2/>class optional;
<ins>
<br/>namespace pmr {
<br/><tab/> // [pmroptional.optional], class template optional
<br/><tab/> template&lt;class T&gt;
<br/><tab2/>class optional;
<br/> }
</ins>
<br/> ...
</tt>
</blockquote>


<p>Modify 20.6.3 Class template optional [optional.optional] </p>
<p>
<blockquote>
<br/>// [optional.ctor], constructors
<br/>...
<ins><tt>
<br/><tab/> template&lt;class U&gt;
<br/><tab2/>      explicit(<i>see below</i>) optional(const pmr::optional&lt;U&gt;&amp;);
<br/><tab/> template&lt;class U&gt;
<br/><tab2/>      explicit(<i>see below</i>) optional(pmr::optional&lt;U&gt;&amp;&amp;);
</tt>
</ins>
<br/>...
<br/>// [optional.assign], assignment
<br/>...
<ins>
<tt>
<br/><tab/>   template&lt;class U&gt; optional&amp; operator=(const pmr::optional&amp;);
<br/><tab/>   template&lt;class U&gt; optional&amp; operator=(pmr::optional&amp;&amp;) noexcept(<i>see below</i>);
</tt>
</ins>
<tt>
<br/>...
<br/><tab/>   template&lt;class T&gt;
<br/><tab/>   optional(T) -&gt; optional&lt;T&gt;;
<ins>
<br/><tab/>   template&lt;class T&gt;
<br/><tab/>   optional(const pmr::optional&lt;T&gt;&amp;) -&gt; optional&lt;T&gt;;
<br/><tab/>   template&lt;class T&gt;
<br/><tab/>   optional(pmr::optional&lt;T&gt;&amp;&amp;) -&gt; optional&lt;T&gt;;

</ins>
</tt>
</blockquote>
</p>

<p>Modify 20.6.3.1 Constructors [optional.ctor] </p>
<p>
<blockquote>
<p>
<br/><code>template&lt;class U&gt; explicit(<i>see below</i>) optional(const optional&lt;U&gt;&amp; v);</code>
...
<br/><tab/><i>Mandates:</i> 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, <del>and</del>
<br/><tab2/><ins> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,<ins>and</ins>
<br/><tab2/><ins> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt> </ins>
...
</p>
<p>
<br/><code>template&lt;class U&gt; explicit(<i>see below</i>) optional(optional&lt;U&gt;&amp;&amp; v);</code>
...
<br/><tab/><i>Mandates:</i> 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, <del>and</del>
<br/><tab2/><ins> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, <ins>and</ins>
<br/><tab2/><ins> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt> </ins>
...
</p>
...
<p>
<ins>
<br/>
<br/><code>template&lt;class U&gt; explicit(<i>see below</i>) optional(const pmr::optional&lt;U&gt;&amp; rhs);</code>
<br/><tab/><i>Effects:</i> If <tt>rhs</tt> contains a value, initializes the contained value 
 as if direct-non-list-initializing an object of type <tt>T</tt> with the expression <tt>*rhs</tt>.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Remarks:</i> <br/><tab/>The expression inside <tt>explicit</tt> is equivalent to:
<br/><tab2/><tt>!is_convertible_v&lt;const U&amp;, T&gt;</tt>
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_same&lt;T,U&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, and
<br/><tab2/> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>
<br/>     

<br/>
<br/><code>template&lt;class U&gt; explicit(<i>see below</i>) optional(pmr::optional&lt;U&gt;&amp;&amp; rhs);</code>
<br/><tab/><i>Effects:</i> If <tt>rhs</tt> contains a value, initializes the contained value 
 as if direct-non-list-initializing an object of type <tt>T</tt> with the expression <tt>std​::​move(*rhs)</tt>.
<tt>std​::​move(*rhs)</tt> as the constructor argument. <tt>bool(rhs)</tt> is unchanged.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Remarks:</i>The expression inside <tt>explicit</tt> is equivalent to:
<br/><tab2/><tt>!is_convertible_v&lt;U, T&gt;</tt>
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T,U&amp;&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_same&lt;T,U&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, and
<br/><tab2/> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>
<br/>    
</p>
</ins></blockquote>

<p>Modify 20.6.3.3 Assignment [optional.assign] </p>
<p>
<blockquote>
...
<br/><tt>template&lt;class U&gt; optional&amp; operator=(const optional&lt;U&gt;&amp; rhs);</tt>
...
<br/><tab/><i>Remarks:</i> ...
This operator shall not participate in overload resolution unless
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_assignable&lt;T&amp;, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_assignable_v&lt;T&amp;, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_assignable_v&lt;T&amp;, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, <del>and</del>
<br/><tab2/><ins>  - <tt>is_assignable_v&lt;T&amp;, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,<ins>and</ins>
<br/><tab2/><ins>  - <tt>is_assignable_v&lt;T&amp;, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt> </ins>
</blockquote>
</p>
<p>
<blockquote>

<br/><tt>template&lt;class U&gt; optional&amp; operator=(optional&lt;U&gt;&amp;&amp; rhs);</tt>
...
<br/><tab/><i>Remarks:</i> ...
This operator shall not participate in overload resolution unless
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_assignable&lt;T&amp;, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_assignable_v&lt;T&amp;, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/><ins>  - <tt>is_assignable_v&lt;T&amp;, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, <del>and</del>
<br/><tab2/><ins>  - <tt>is_assignable_v&lt;T&amp;, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, </ins>
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,<ins>and</ins> 
<br/><tab2/><ins>  - <tt>is_assignable_v&lt;T&amp;, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt> </ins>
</blockquote>
</p>

<blockquote><ins>
<br/>
<br/><tt>template&lt;class U&gt; optional&amp; operator=(const pmr::optional&lt;U&gt;&amp; rhs);</tt>
<br/><tab/><i>Effects:</i> See Table
<blockquote>
<table border="1">
<caption><ins>Table &mdash; <tt>optional operator=(const pmr::optional&lt;U&gt;&amp;)</tt> effects</ins></caption>
<tr>
<th></th>
<th><ins><tt>*this</tt> contains a value</ins></th>
<th><ins><tt>*this</tt> does not contain a value</ins></th>
</tr>
<tr>
<td><ins><tt>rhs</tt> contains a value</ins></td>
<td><ins>assigns <tt>*rhs</tt> to the contained value</ins></td>
<td><ins>initializes the contained value as if direct-non-list-initializing an object of type <tt>T</tt> with <tt>*rhs</tt>.</ins></td>
</tr>
<tr>
<td><ins><tt>rhs</tt> does not contain a value</ins></td>
<td><ins>destroys the contained value by calling <tt>val->T::~T()</tt></ins></td>
<td><ins>no effect</ins></td>
</tr>
</table></blockquote>
<br/><tab/><i>Returns:</i> <tt>*this</tt>.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Remarks:</i>  If any exception is thrown, the result of the expression <tt>bool(*this)</tt>
remains unchanged. If an exception is thrown during the call to <tt>T</tt>'s constructor,
the state of <tt>*rhs.val</tt> is determined by the exception safety guarantee of <tt>T</tt>'s constructor.
If an exception is thrown during the call to <tt>T</tt>'s assignment, the state of <tt>*val</tt> and <tt>*rhs.val</tt> is
determined by the exception safety guarantee of <tt>T</tt>'s assignment.
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_same&lt;T,U&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_assignable&lt;T&amp;, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const U&amp;, T&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, and
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>

<br/>
<br/><tt>template&lt;class U&gt; optional&amp; operator=(pmr::optional&lt;U&gt;&amp;&amp; rhs);</tt>
<br/><tab/><i>Effects:</i> See Table
<blockquote>
<table border="1">
<caption><ins>Table &mdash; <tt>optional operator=(pmr::optional&lt;U&gt;&amp;&amp;)</tt> effects</ins></caption>
<tr>
<th></th>
<th><ins><tt>*this</tt> contains a value</ins></th>
<th><ins><tt>*this</tt> does not contain a value</ins></th>
</tr>
<tr>
<td><ins><tt>rhs</tt> contains a value</ins></td>
<td><ins>assigns <tt>*rhs</tt> to the contained value</ins></td>
<td><ins>initializes the contained value as if direct-non-list-initializing an object of type <tt>T</tt> with <tt>std​::​move(*rhs)</tt></ins></td>
</tr>
<tr>
<td><ins><tt>rhs</tt> does not contain a value</ins></td>
<td><ins>destroys the contained value by calling <tt>val->T::~T()</tt></ins></td>
<td><ins>no effect</ins></td>
</tr>
</table></blockquote>
<br/><tab/><i>Returns:</i> <tt>*this</tt>.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Remarks:</i>   If any exception is thrown, the result of the expression <tt>bool(*this)</tt>
remains unchanged. If an exception is thrown during the call to <tt>T</tt>'s constructor,
the state of <tt>*rhs.val</tt> is determined by the exception safety guarantee of <tt>T</tt>'s constructor.
If an exception is thrown during the call to <tt>T</tt>'s assignment, the state of <tt>*val</tt> and <tt>*rhs.val</tt> is
determined by the exception safety guarantee of <tt>T</tt>'s assignment.
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_assignable&lt;T&amp;, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const U&amp;, T&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const pmr::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const pmr::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, and
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const pmr::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>


</ins></blockquote>

<p>
Insert new sections after 20.6.3 Class template optional [optional.optional]
</p>
<ins>
<p><h3><ins> Header &lt;optional&gt; synopsis [pmroptional.sys]</pmroptional></ins></h3>

<blockquote><ins><code>
namespace std::pmr {	
<br/><tab/>  // [pmroptional.optional]
<br/><tab/>   template&lt;class T&gt;
<br/><tab2/>     class optional;
<br/>		  
<br/><tab/>  // [pmroptional.traits], allocator-related traits
<br/><tab/>    template&lt;class T&gt;
<br/><tab2/>   struct uses_allocator&ltT, polymorphic_allocator&lt;&gt;&gt;;
<br/>
<br/><tab/>   template&lt;class T&gt;
<br/><tab2/>  constexpr bool uses-poly-alloc = uses_allocator&lt;T, pmr::polymorphic_allocator&lt;&gt;&gt;::value;   // exposition only
<br/>
 <br/><tab/>  // [pmroptional.relops], relational operators
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator==(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator==(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator==(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator!=(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator!=(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator!=(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&lt;(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&lt;(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&lt;(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&gt;(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&gt;(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&gt;(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&lt;=(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&lt;=(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&lt;=(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&gt;=(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&gt;=(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;
<br/><tab2/>	bool operator&gt;=(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, three_way_comparable_with&lt;T&gt; U&gt;
<br/><tab2/>	compare_three_way_result_t&lt;T,U&gt;
<br/><tab/><tab2/>      operator&lt;=&gt;(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, three_way_comparable_with&lt;T&gt; U&gt;
<br/><tab2/>	compare_three_way_result_t&lt;T,U&gt;
<br/><tab/><tab2/>      operator&lt;=&gt;(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, three_way_comparable_with&lt;T&gt; U&gt;
<br/><tab2/>	compare_three_way_result_t&lt;T,U&gt;
<br/><tab/><tab2/>      operator&lt;=&gt;(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/>
<br/><tab/>  // [pmroptional.nullops], comparison with nullopt
<br/><tab/>   template&lt;class T&gt; bool operator==(const optional&lt;T&gt;&amp;, nullopt_t) noexcept;
<br/><tab/>   template&lt;class T&gt;
<br/><tab2/>	strong_ordering operator&lt;=&gt;(const optional&lt;T&gt;&amp;, nullopt_t) noexcept;
<br/>
 <br/><tab/> // [pmroptional.comp.with.t], comparison with T
<br/><tab/>   template&lt;class T, class U&gt; bool operator==(const optional&lt;T&gt;&amp;, const U&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator==(const T&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator!=(const optional&lt;T&gt;&amp;, const U&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator!=(const T&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&lt;(const optional&lt;T&gt;&amp;, const U&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&lt;(const T&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&gt;(const optional&lt;T&gt;&amp;, const U&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&gt;(const T&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&lt;=(const optional&lt;T&gt;&amp;, const U&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&lt;=(const T&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&gt;=(const optional&lt;T&gt;&amp;, const U&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&gt;=(const T&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, three_way_comparable_with&lt;T&gt; U&gt;
<br/><tab2/>	compare_three_way_result_t&lt;T,U&gt;
<br/><tab/><tab2/>      operator&lt;=&gt;(const optional&lt;T&gt;&amp;, const U&amp;);
<br/>
 <br/><tab/> // [pmroptional.specalg], specialized algorithms
<br/><tab/>   template&lt;class T&gt;
<br/><tab2/>    void swap(optional&lt;T&gt;&amp;, optional&lt;T&gt;&amp;) ;
<br/>
<br/><tab/>   template&lt;class T&gt;
<br/><tab2/>	constexpr optional&lt;<i>see below</i>&gt; make_optional(T&amp;&amp;);
<br/><tab/>   template&lt;class T&gt;
<br/><tab2/>    constexpr optional&lt;T&gt; make_optional();
<br/><tab/>   template&lt;class T, class Arg0, class... Args>
<br/><tab2/>	constexpr optional&lt;T&gt; make_optional(Arg0 arg0&amp;&amp;, Args&amp;&amp;... args);
<br/><tab/>   template&lt;class T, class U, class... Args>
<br/><tab2/>	constexpr optional&lt;T&gt; make_optional(initializer_list&lt;U&gt; il, Args&amp;&amp;... args);
<br/>
<br/><tab/>   template&lt;class T&gt;
<br/><tab2/>	constexpr optional&lt;<i>see below</i>&gt; make_optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp; a, T&amp;&amp;);
<br/><tab/>   template&lt;class T, class... Args>
<br/><tab2/>	constexpr optional&lt;T&gt; make_optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp; a, Args&amp;&amp;... args);
<br/><tab/>   template&lt;class T, class U, class... Args>
<br/><tab2/>	constexpr optional&lt;T&gt; make_optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp; a, initializer_list&lt;U&gt; il, Args&amp;&amp;... args);
<br/>
 <br/><tab/> // [pmroptional.hash], hash support
<br/><tab/>   template&lt;class T&gt; struct hash&lt;optional&lt;T&gt;&gt;;
<br/>}

</code></ins></blockquote></p>

<p><h3><ins> Class template optional  [optional.pmroptional]</ins></h3></p>
<p>
<blockquote><ins>
<code>
namespace std::pmr {
 <br/><tab/>   template&lt;class T&gt;
<br/><tab/> class optional <i> see below</i>{
<br/><tab/> public:
<br/><tab2/> using value_type = T;
<br/><tab2/> using allocator_type = polymorphic_allocator&lt;&gt;; // <i>not always defined, see below</i>
<br/>
<br/><tab2/>    // [pmroptional.ctor], constructors
    <br/><tab2/>optional() noexcept;
    <br/><tab2/>optional(nullopt_t) noexcept;
    <br/><tab2/>optional(const optional&amp;);
    <br/><tab2/>optional(optional&amp;&amp;) noexcept(<i>see below</i>);
    <br/><tab2/>optional(const std::optional&amp;);
    <br/><tab2/>optional(std::optional&amp;&amp;);	
    <br/><tab2/>template&lt;class... Args&gt;
      <br/><tab2/><tab/>explicit optional(in_place_t, Args&amp;&amp;...);
    <br/><tab2/>template&lt;class U, class... Args&gt;
      <br/><tab2/><tab/>explicit optional(in_place_t, initializer_list&lt;U&gt;, Args&amp;&amp;...);
    <br/><tab2/>template&lt;class U = T&gt;
      <br/><tab2/><tab/>explicit(<i>see below</i>) optional(U&amp;&amp;);
    <br/><tab2/>template&lt;class U&gt;
      <br/><tab2/><tab/>explicit(<i>see below</i>) optional(const optional&lt;U&gt;&amp;);
    <br/><tab2/>template&lt;class U&gt;
      <br/><tab2/><tab/>explicit(<i>see below</i>) optional(optional&lt;U&gt;&amp;&amp;);
	<br/><tab2/>template&lt;class U&gt;
      <br/><tab2/><tab/>explicit(<i>see below</i>) optional(const std::optional&lt;U&gt;&amp;);
    <br/><tab2/>template&lt;class U&gt;
      <br/><tab2/><tab/>explicit(<i>see below</i>) optional(std::optional&lt;U&gt;&amp;&amp;);
      <br/>
    <br/><tab2/>// allocator-extended constructors  
    <br/><tab2/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;) noexcept; // <i>not always provided, see below</i>
    <br/><tab2/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, nullopt_t) noexcept; // <i>not always provided, see below</i>
    <br/><tab2/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, const optional&amp;); // <i>not always provided, see below</i>
    <br/><tab2/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, optional&amp;&amp;) noexcept(<i>see below</i>); // <i>not always provided, see below</i>
    <br/><tab2/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, const std::optional&amp;); // <i>not always provided, see below</i>
    <br/><tab2/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, std::optional&amp;&amp;); // <i>not always provided, see below</i>
    <br/><tab2/>template&lt;class... Args&gt;
      <br/><tab2/><tab/>explicit optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, in_place_t,  Args&amp;&amp;...); // <i>not always provided, see below</i>
    <br/><tab2/>template&lt;class U, class... Args&gt;
      <br/><tab2/><tab/>explicit optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, in_place_t, initializer_list&lt;U&gt;, Args&amp;&amp;...); // <i>not always provided, see below</i>
    <br/><tab2/>template&lt;class U = T&gt; 
      <br/><tab2/><tab/>explicit(<i>see below</i>) optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;,U&amp;&amp;); // <i>not always provided, see below</i>
    <br/><tab2/>template&lt;class U&gt;
      <br/><tab2/><tab/>explicit(<i>see below</i>) optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;,const optional&lt;U&gt;&amp;); // <i>not always provided, see below</i>
    <br/><tab2/>template&lt;class U&gt;
      <br/><tab2/><tab/>explicit(<i>see below</i>) optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;,optional&lt;U&gt;&amp;&amp;); // <i>not always provided, see below</i>
	<br/><tab2/>template&lt;class U&gt;
      <br/><tab2/><tab/>explicit(<i>see below</i>) optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;,const std::optional&lt;U&gt;&amp;); // <i>not always provided, see below</i>
    <br/><tab2/>template&lt;class U&gt;
      <br/><tab2/><tab/>explicit(<i>see below</i>) optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;,std::optional&lt;U&gt;&amp;&amp;);  // <i>not always provided, see below</i>
<br/>
<br/><tab2/>    // [pmroptional.dtor], destructor
<br/><tab2/>    ~optional();
<br/>
<br/><tab2/>    // [pmroptional.assign], assignment
<br/><tab2/>    optional&amp; operator=(nullopt_t) noexcept;
<br/><tab2/>    optional&amp; operator=(const optional&amp;);
<br/><tab2/>    optional&amp; operator=(optional&amp;&amp;) noexcept(<i>see below</i>);
<br/><tab2/>    template&lt;class U = T&gt; optional&amp; operator=(U&amp;&amp;);
<br/><tab2/>    template&lt;class U&gt; optional&amp; operator=(const optional&lt;U&gt;&amp;);
<br/><tab2/>    template&lt;class U&gt; optional&amp; operator=(optional&lt;U&gt;&amp;&amp;);
<br/><tab2/>    template&lt;class U&gt; optional&amp; operator=(const std::optional&lt;U&gt;&amp;);
<br/><tab2/>    template&lt;class U&gt; optional&amp; operator=(std::optional&lt;U&gt;&amp;&amp;);
<br/><tab2/>    template&lt;class... Args&gt;> T&amp; emplace(Args&amp;&amp;...);
<br/><tab2/>    template&lt;class U, class... Args&gt; T&amp; emplace(initializer_list&lt;U&gt;, Args&amp;&amp;...);
<br/>
<br/><tab2/>    // [pmroptional.swap], swap
<br/><tab2/>    void swap(optional&amp;) noexcept(<i>see below</i>);
<br/>
<br/><tab2/>    // [pmroptional.observe], observers
<br/><tab2/>    const T* operator-&gt;() const;
<br/><tab2/>    T* operator-&gt;();
<br/><tab2/>    const T&amp; operator*() const&amp;;
<br/><tab2/>    T&amp; operator*() &amp;;
<br/><tab2/>    T&amp;&amp; operator*() &amp;&amp;;
<br/><tab2/>    const T&amp;&amp; operator*() const&amp;&amp;;
<br/><tab2/>    explicit operator bool() const noexcept;
<br/><tab2/>    bool has_value() const noexcept;
<br/><tab2/>    const T&amp; value() const&amp;;
<br/><tab2/>    T&amp; value() &amp;;
<br/><tab2/>    T&amp;&amp; value() &amp;&amp;;
<br/><tab2/>    const T&amp;&amp; value() const&amp;&amp;;
<br/><tab2/>    template&lt;class U&gt; T value_or(U&amp;&amp;) const&amp;;
<br/><tab2/>    template&lt;class U&gt; T value_or(U&amp;&amp;) &amp;&amp;;
<br/><tab2/>    template&lt;class U&gt; T value_or(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, U&amp;&amp;) const&amp;; // <i>not always provided, see below</i>
<br/><tab2/>    template&lt;class U&gt; T value_or(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, U&amp;&amp;) &amp;&amp;; // <i>not always provided, see below</i>
<br/><tab2/>    allocator_type get_allocator() const noexcept;

<br/>
 <br/><tab2/>   // [pmroptional.mod], modifiers
<br/><tab2/>    void reset() noexcept;
<br/>
<br/><tab/>  private:
<br/><tab2/>    T* val;         // exposition only
<br/><tab2/>    const polymorphic_allocator&lt;&gt;  <i>alloc</i>;         // <i> exposition only; not always provided, see below</i>
<br/><tab/>  };
<br/>
<br/><tab/>   template&lt;class T&gt;
<br/><tab/>   optional(T) -&gt; optional&lt;T&gt;;
<ins>
<br/><tab/>   template&lt;class T&gt;
<br/><tab/>   optional(const std::optional&lt;T&gt;&amp;) -&gt; optional&lt;T&gt;;
<br/><tab/>   template&lt;class T&gt;
<br/><tab/>   optional(std::optional&lt;T&gt;&amp;&amp;) -&gt; optional&lt;T&gt;;
<br/>
<br/>}
</code>
</blockquote></ins></p>

<blockquote><ins>Any instance of optional&lt;T&gt; at any given time either contains a value or does not contain a value. 
When an instance of <i>optional</i>&lt;T&gt; contains a value, it means that an object of type <tt>T</tt> 
is allocated within the storage of the <i>optional</i> object. Implementations are not permitted to use 
additional storage, such as dynamic memory, to allocate its contained value. The contained value shall be allocated in a 
region of the <i>optional</i>&lt;T&gt; storage suitably aligned for the type <tt>T</tt> and, if <tt>uses-poly-alloc</tt> is true,
constructed by uses-allocator construction 
with allocator <tt><i>alloc</i></tt>. When an object of type <i>optional</i>&lt;T&gt; is contextually 
converted to bool, the conversion returns true if the object contains a value; otherwise the conversion returns false.
</ins></blockquote>
<blockquote><ins>Member <tt>val</tt> is provided for exposition only. When an <i>optional</i>&lt;T&gt;
object contains a value, val points to the contained value.
</ins></blockquote>
<blockquote><ins>If and only if <tt>uses-poly-alloc</tt> is <tt>false</tt>, optional&lt;T&gt; publicly inherits from 
std::optional&lt;T&gt;
</ins></blockquote>
<blockquote><ins>If and only if <tt>uses-poly-alloc</tt> is <tt>true</tt>, the following applies :
<br/> - <tt>allocator_type</tt> will be defined,
<br/> - exposition only member <tt><i>alloc</i></tt> will be provided and will be used to create the contained value, if any, and
<br/> - if <tt>T</tt> provides a <tt>get_allocator()</tt> member function whose return type is convertible to <tt>polymorphic_allocator&lt;&gt;</tt>, the implementation is 
allowed to assume that the allocator used for constructing the element is the same allocator as returned 
by <tt>T::get_allocator()</tt>. [<i>Note:</i> In such an implementation, <tt>pmr::optional&lt;pmr::string&gt;</tt> 
will be zero-overhead compared to <tt>optional&lt;pmr::string&gt;</tt>. -- <i>end note</i>]
</ins></blockquote>
<blockquote><ins><tt>T</tt> shall be a type other than <tt><i>cv</i> in_­place_­t</tt>, <tt><i>cv</i> allocator_arg_­t</tt>, or <tt><i>cv</i> nullopt_­t</tt> 
that meets the <i>Cpp17Destructible</i> requirements (Table 30).</ins></blockquote>



<p><h4><ins> Constructors [pmroptional.ctor]</ins></h4></p>
<p><blockquote><ins>
<br/><code>optional() noexcept;</code>
<br/><code>optional(nullopt_t) noexcept;</code>
<br/><tab/><i>Effects:</i> If <tt>uses-poly-alloc</tt> is <tt>true</tt>, <tt><i>alloc</i></tt> is default initialized</tt>
<br/><tab/><i>Ensures:</i> *this does not contain a value.
<br/><tab/><i>Remarks:</i> No contained value is initialized.
<br/>
<br/><code>optional(const optional&amp;);</code>
<br/><tab/><i>Effects:</i> If <tt>uses-poly-alloc</tt> is <tt>true</tt>, <tt><i>alloc</i></tt> is default initialized</tt>. 
If <tt>rhs</tt> contains a value, constructs the contained value with uses-allocator construction ([allocator.uses.construction]) with <i>alloc</i> and 
the expression <tt>*rhs</tt>.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Mandates:</i><tt>is_­copy­_constructible_­v&lt;T&gt;</tt> is true.

<br/>
<br/><code>optional(optional&amp;&amp; rhs) noexcept(<i>see below</i>)</code>
<br/><tab/><i>Effects:</i> If <tt>uses-poly-alloc</tt> is <tt>true</tt>, <tt><i>alloc</i></tt> is initialized with <tt>rhs.<i>alloc</i></tt>. 
If <tt>rhs</tt> contains a value, constructs the contained value with uses-allocator construction ([allocator.uses.construction]) with <i>alloc</i> and 
the expression <tt>std​::​move(*rhs)</tt>. <tt>bool(rhs)</tt> is unchanged.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Remarks:</i> The expression inside <tt>noexcept</tt> is equivalent to <tt>is_­nothrow_­move_­constructible_­v&lt;T&gt;</tt>.
<br/><tab/><i>Mandates:</i><tt>is_­move_­constructible_­v&lt;T&gt;</tt> is true.
<br/>
<br/><code>optional(const std::optional&amp;);</code>
<br/><tab/><i>Effects:</i> If <tt>uses-poly-alloc</tt> is <tt>true</tt>, <tt><i>alloc</i></tt> is default initialized</tt>. 
If <tt>rhs</tt> contains a value, initializes the contained value 
with the expression <tt>*rhs</tt>.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Mandates:</i><tt>is_­copy­_constructible_­v&lt;T&gt;</tt> is true.

<br/>
<br/><code>optional(std::optional&amp;&amp; rhs)</code>
<br/><tab/><i>Effects:</i> If <tt>uses-poly-alloc</tt> is <tt>true</tt>, <tt><i>alloc</i></tt> is initialized with <tt>rhs.<i>alloc</i></tt>. 
If <tt>rhs</tt> contains a value, constructs the contained value with uses-allocator construction ([allocator.uses.construction]) 
with <i>alloc</i> and the expression <tt>std​::​move(*rhs)</tt>. <tt>bool(rhs)</tt> is unchanged.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Mandates:</i><tt>is_­move_­constructible_­v&lt;T&gt;</tt> is true.


<br/>
<br/><code>template&lt;class... Args&gt; explicit optional(in_place_t, Args&amp;&amp;... args);</code>
<br/><tab/><i>Effects:</i> If <tt>uses-poly-alloc</tt> is <tt>true</tt>, <tt><i>alloc</i></tt> is default initialized</tt>.  
Constructs the contained value with uses-allocator construction ([allocator.uses.construction]) with <i>alloc</i> and <tt>std​::​forward&lt;Args&gt;(args)....</tt>. 
<br/><tab/><i>Ensures:</i> <tt>*this</tt> contains a value..
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Mandates:</i><tt>is_­copy_­constructible_­v&lt;T&gt;</tt> is true.

<br/>
<br/><code>template&lt;class... Args&gt; explicit optional(in_place_t, initializer_list&lt;U&gt; il, Args&amp;&amp;... args);</code>
<br/><tab/><i>Effects:</i>  If <tt>uses-poly-alloc</tt> is <tt>true</tt>, <tt><i>alloc</i></tt> is default initialized</tt>. 
Constructs the contained value with uses-allocator construction ([allocator.uses.construction]) with <i>alloc</i>, <tt>il, and std​::​forward&lt;Args&gt;(args)....</tt>.
<br/><tab/><i>Ensures:</i> <tt>*this</tt> contains a value..
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Mandates:</i><tt>is_­constructible_­v&lt;T, initializer_­list&lt;U&gt;&amp;, Args&amp;&amp;...&gt;</tt> is true.  
<br/>
<br/><code>template&lt;class U = T&gt; explicit(<i>see below</i>) optional(U&amp;&amp; rhs);</code>
<br/><tab/><i>Effects:</i>If <tt>uses-poly-alloc</tt> is <tt>true</tt>, <tt><i>alloc</i></tt> is default initialized</tt>.
Constructs the contained value with uses-allocator construction ([allocator.uses.construction]) with <i>alloc</i> and <tt> std​::​forward&lt;U&gt;(rhs)</tt>. 
<br/><tab/><i>Ensures:</i> <tt>*this</tt> contains a value.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Remarks:</i>The expression inside <tt>explicit</tt> is equivalent to:
<br/><tab2/><tt>!is_convertible_v&lt;U, T&gt;</tt> 
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, U&amp;&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­same_­v&lt;remove_­cvref_­t&lt;U&gt;, in_­place_­t&gt</tt>
is <tt>false</tt>, and
<br/><tab2/> - <tt>is_­same_­v&lt;remove_­cvref_­t&lt;U&gt;,optional&gt</tt> is <tt>false</tt>. 

<br/>
<br/><code>template&lt;class U&gt; explicit(<i>see below</i>) optional(const optional&lt;U&gt;&amp; rhs);</code>
<br/><tab/><i>Effects:</i>If <tt>uses-poly-alloc</tt> is <tt>true</tt>, <tt><i>alloc</i></tt> is default initialized</tt>. 
If <tt>rhs</tt> contains a value, constructs the contained value with uses-allocator construction ([allocator.uses.construction]) 
with <i>alloc</i> and <tt>*rhs</tt>. 
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Remarks:</i>The expression inside <tt>explicit</tt> is equivalent to:
<br/><tab2/><tt>!is_convertible_v&lt;const U&amp;, T&gt;</tt>
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const U&amp;&gt;</tt> is <tt>true</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, and
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt> 
<br/>     


<br/>
<br/><code>template&lt;class U&gt; explicit(<i>see below</i>) optional(optional&lt;U&gt;&amp;&amp; rhs);</code>
<br/><tab/><i>Effects:</i>If <tt>uses-poly-alloc</tt> is <tt>true</tt>, <tt><i>alloc</i></tt> is default initialized</tt>.
If <tt>rhs</tt> contains a value, constructs the contained value with uses-allocator construction ([allocator.uses.construction]) 
with <i>alloc</i> and <tt>std​::​move(*rhs)</tt>. <tt>bool(rhs)</tt> is unchanged.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Remarks:</i>The expression inside <tt>explicit</tt> is equivalent to:
<br/><tab2/><tt>!is_convertible_v&lt;U, T&gt;</tt 
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T,U&amp;&amp;&gt;</tt> is <tt>true</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, and
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt> 
<br/>    

<br/>
<br/><code>template&lt;class U&gt; explicit(<i>see below</i>) optional(const std::optional&lt;U&gt;&amp; rhs);</code>
<br/><tab/><i>Effects:</i>If <tt>uses-poly-alloc</tt> is <tt>true</tt>, <tt><i>alloc</i></tt> is default initialized</tt>.
If <tt>rhs</tt> contains a value, constructs the contained value with uses-allocator construction ([allocator.uses.construction]) 
with <i>alloc</i> and <tt>*rhs</tt>. 
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Remarks:</i>The expression inside <tt>explicit</tt> is equivalent to:
<br/><tab2/><tt>!is_convertible_v&lt;const U&amp;, T&gt;</tt>
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, and
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>
<br/>     


<br/>
<br/><code>template&lt;class U&gt; explicit(<i>see below</i>) optional(std::optional&lt;U&gt;&amp;&amp; rhs);</code>
<br/><tab/><i>Effects:</i>If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, <tt><i>alloc</i></tt> is default initialized</tt>. 
If <tt>rhs</tt> contains a value, constructs the contained value with uses-allocator construction ([allocator.uses.construction]) 
with <i>alloc</i> and <tt>std​::​move(*rhs)</tt>. 
<tt>bool(rhs)</tt> is unchanged.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Remarks:</i><br/><tab/>The expression inside <tt>explicit</tt> is equivalent to:
<br/><tab2/><tt>!is_convertible_v&lt;U, T&gt;</tt>
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T,U&amp;&amp;&gt;</tt> is <tt>true</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>, 
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>, and 
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt> 
<br/>  
    <br/>
    
    
<code> 
	<br/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;) noexcept;
  <br/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, nullopt_t) noexcept;
    <br/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, const optional&amp;);
    <br/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, optional&amp;&amp;) noexcept(<i>see below</i>);
	
    <br/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, const std::optional&amp;);
    <br/>optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, std::optional&amp;&amp;);
    <br/>template&lt;class... Args&gt;
      <br/><tab/>explicit optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, in_place_t, Args&amp;&amp;...);
    <br/>template&lt;class U, class... Args&gt;
      <br/><tab/>explicit optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;, in_place_t, initializer_list&lt;U&gt;, Args&amp;&amp;...);
    <br/>template&lt;class U = T&gt;
      <br/><tab/>explicit(<i>see below</i>) optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;,U&amp;&amp;);
    <br/>template&lt;class U&gt;
      <br/><tab/>explicit(<i>see below</i>) optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;,const optional&lt;U&gt;&amp;);
    <br/>template&lt;class U&gt;
      <br/><tab/>explicit(<i>see below</i>) optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;,optional&lt;U&gt;&amp;&amp;);
	<br/>template&lt;class U&gt;
      <br/><tab/>explicit(<i>see below</i>) optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;,const std::optional&lt;U&gt;&amp;);
    <br/>template&lt;class U&gt;
      <br/><tab/>explicit(<i>see below</i>) optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp;,std::optional&lt;U&gt;&amp;&amp;);  
 </code>
<br/><tab/><i>Constraints:</i> <tt>uses_allocator&lt;T,polymorphic_allocator&lt;&gt;&gt;</tt> is true;
<br/><tab/><i>Effects:</i> Equivalent to the preceding constructors except that <tt><i>alloc</i></tt> is initialized with <tt>a</tt>.
      </blockquote></ins></p>

<p><h4><ins> Destructor [pmroptional.dtor]</ins></h4></p>
<blockquote><ins>
<br/><tt>~optional();</tt>
<br/><tab/><i>Effects:</i> If <tt>is_­trivially_­destructible_­v&lt;T&gt; != true</tt> and <tt>*this</tt> contains a value, calls
<tt>val->T::~T()</tt>
<br/><tab/><i>Remarks:</i> If <tt>is_­trivially_­destructible_­v&lt;T&gt;</tt> is <tt>true</tt>, then this destructor is trivial.
</ins></blockquote>

<p><h4><ins> Assignment [pmroptional.assign]</ins></h4></p>
<blockquote><ins>
<br/><tt>optional&lt;T&gt;&amp; operator=(nullopt_t) noexcept;</tt>
<br/><tab/><i>Effects:</i> If <tt>*this</tt> contains a value, calls <tt>val->T::~T()</tt> to destroy the contained value; otherwise
no effect.
<br/><tab/><i>Remarks:</i> <tt>*this</tt>
<br/><tab/><i>Ensures:</i> <tt>*this</tt> does not contain a value.


<br/>
<br/><tt>optional&lt;T&gt;&amp; operator=(const optional&amp; rhs);</tt>
<br/><tab/><i>Effects:</i> See Table
<blockquote><table border="1">
<caption><ins>Table &mdash; <tt>optional operator=(const optional&amp; rhs)</tt> effects</ins></caption>
<tr>
<th></th>
<th><ins><tt>*this</tt> contains a value</ins></th>
<th><ins><tt>*this</tt> does not contain a value</ins></th>
</tr>
<tr>
<td><ins><tt>rhs</tt> contains a value</ins></td>
<td><ins>assigns <tt>*rhs</tt> to the contained value</ins></td>
<td><ins>initializes the contained value with <tt>*rhs</tt>. 
If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, initialization is done by uses-allocator construction 
with allocator <tt><i>alloc</i></tt> </ins></td>
</tr>
<tr>
<td><ins><tt>rhs</tt> does not contain a value</ins></td>
<td><ins>destroys the contained value by calling <tt>val->T::~T()</tt></ins></td>
<td><ins>no effect</ins></td>
</tr>
</table></blockquote>
<br/><tab/><i>Returns:</i> <tt>*this</tt>.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Remarks:</i> If any exception is thrown, the result of the expression <tt>bool(*this)</tt> remains unchanged.
If an exception is thrown during the call to <tt>T</tt>'s copy constructor, no effect. If an exception is thrown during the 
call to <tt>T</tt>'s copy assignment, the state of of its contained value is as defined by the exception safety guarantee of
is determined by the exception safety guarantee of <tt>T</tt>'s copy assignment.
This operator shall be defined as deleted unless <tt>is_­copy_­constructible_­v&lt;T&gt;</tt> is <tt>true</tt> and
<tt>is_­copy_­assignable_­v&lt;T&gt;</tt> is <tt>true</tt>. 

<br/>
<br/><tt>optional&lt;T&gt;&amp; operator=(optional&amp;&amp; rhs) noexcept(<i>see below</i>);</tt>
<br/><tab/><i>Effects:</i> See Table
<blockquote>
<table border="1">
<caption><ins>Table &mdash; <tt>optional operator=(optional&amp;&amp; rhs)</tt> effects</ins></caption>
<tr>
<th></th>
<th><ins><tt>*this</tt> contains a value</ins></th>
<th><ins><tt>*this</tt> does not contain a value</ins></th>
</tr>
<tr>
<td><ins><tt>rhs</tt> contains a value</ins></td>
<td><ins>assigns <tt>std​::​move(*rhs)</tt> to the contained value</ins></td>
<td><ins>initializes the contained value with <tt>std​::​move(*rhs)</tt>. 
If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, initialization is done by uses-allocator construction 
with allocator <tt><i>alloc</i></tt> </ins></td>
</tr>
<tr>
<td><ins><tt>rhs</tt> does not contain a value</ins></td>
<td><ins>destroys the contained value by calling <tt>val->T::~T()</tt></ins></td>
<td><ins>no effect</ins></td>
</tr>
</table></blockquote>
<br/><tab/><i>Returns:</i> <tt>*this</tt>.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Remarks:</i> The expression inside <tt>noexcept</tt> is equivalent to:
<br/><tab2/><code>is_nothrow_move_assignable_v&lt;T&gt; && is_nothrow_move_constructible_v&lt;T&gt;</code>
<br/><tab/>If any exception is thrown, the result of the expression <tt>bool(*this)</tt> remains unchanged.
If an exception is thrown during the call to <tt>T</tt>'s move constructor, the state of <tt>*rhs.val</tt> is determined by
the exception safety guarantee of <tt>T</tt>'s move constructor. If an exception is thrown during the call to <tt>T</tt>'s move assignment,
the state of <tt>*val</tt> and <tt>*rhs.val</tt> is determined by the exception safety guarantee of <tt>T</tt>'s move assignment.
<br/><tab/><i>Mandates:</i> is_­move_­constructible_­v&lt;T&gt;</tt> is <tt>true</tt> and
 <tt>is_­move_­assignable_­v&lt;T&gt;</tt> is <tt>true</tt>.


<br/>
<br/><code>template&lt;class U = T&gt; optional&amp; operator=(U&amp;&amp; v);</code>
<br/><tab/><i>Effects:</i> If <tt>*this</tt> contains a value, assigns <tt>std​::​forward&lt;U&gt;(v)</tt> to the contained value;
otherwise initializes the contained value with <tt>std​::​forward&lt;U&gt;(v)</tt>. If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, initialization is done by uses-allocator construction
with allocator <tt><i>alloc</i></tt>
<br/><tab/><i>Returns:</i> <tt>*this</tt>.
<br/><tab/><i>Ensures:</i> <tt>*this</tt> contains a value.
<br/><tab/><i>Remarks: If any exception is thrown, the result of the expression <tt>bool(*this)</tt> remains unchanged.
If an exception is thrown during the call to <tt>T</tt>'s constructor, the state of <tt>v</tt> is determined by the exception
safety guarantee of <tt>T</tt>'s constructor. If an exception is thrown during the call to <tt>T</tt>'s assignment,
the state of <tt>*val</tt> and <tt>v</tt> is determined by the exception safety guarantee of <tt>T</tt>'s assignment.
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_­same_­v&lt;remove_­cvref_­t&lt;U&gt;, alloc-optional&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>conjunction_­v&lt;is_­scalar&lt;T&gt;, is_­same&lt;T, decay_­t&lt;U&gt;&gt;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T,U&gt;</tt> is <tt>true</tt>, and
<br/><tab2/> - <tt>is_­assignable_­v&lt;T&amp;,U&gt;</tt> is <tt>true</tt>

<br/>
<br/><tt>template&lt;class U&gt; optional&amp; operator=(const optional&lt;U&gt;&amp; rhs);</tt>
<br/><tab/><i>Effects:</i> See Table
<blockquote>
<table border="1">
<caption><ins>Table &mdash; <tt>optional operator=(const optional&lt;U&gt;&amp;)</tt> effects</ins></caption>
<tr>
<th></th>
<th><ins><tt>*this</tt> contains a value</ins></th>
<th><ins><tt>*this</tt> does not contain a value</ins></th>
</tr>
<tr>
<td><ins><tt>rhs</tt> contains a value</ins></td>
<td><ins>assigns <tt>*rhs</tt> to the contained value</ins></td>
<td><ins>initializes the contained value with <tt>*rhs</tt>.
If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, initialization is done by uses-allocator construction 
with allocator <tt><i>alloc</i></tt> </ins></td>
</tr>
<tr>
<td><ins><tt>rhs</tt> does not contain a value</ins></td>
<td><ins>destroys the contained value by calling <tt>val->T::~T()</tt></ins></td>
<td><ins>no effect</ins></td>
</tr>
</table></blockquote>
<br/><tab/><i>Returns:</i> <tt>*this</tt>.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Remarks:</i> If any exception is thrown, the result of the expression <tt>bool(*this)</tt> remains unchanged.
If an exception is thrown during the call to <tt>T</tt>'s constructor, no effect. If an exception is thrown during the call
to <tt>T</tt>'s assignment, the state of <tt>*val</tt>  is determined by the exception safety guarantee of <tt>T</tt>'s assignment.
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_same&lt;T,U&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_assignable&lt;T&amp;, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, and
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>


<br/>
<br/><tt>template&lt;class U&gt; optional&amp; operator=(const std::optional&lt;U&gt;&amp; rhs);</tt>
<br/><tab/><i>Effects:</i> The result of the expression <tt>bool(rhs)</tt> remains unchanged. See Table
<blockquote>
<table border="1">
<caption><ins>Table &mdash; <tt>optional operator=(const std::optional&lt;U&gt;&amp;)</tt> effects</ins></caption>
<tr>
<th></th>
<th><ins><tt>*this</tt> contains a value</ins></th>
<th><ins><tt>*this</tt> does not contain a value</ins></th>
</tr>
<tr>
<td><ins><tt>rhs</tt> contains a value</ins></td>
<td><ins>assigns <tt> std​::​move(*rhs)</tt> to the contained value</ins></td>
<td><ins>initializes the contained value with <tt> std​::​move(*rhs)</tt>.
If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, initialization is done by uses-allocator construction 
with allocator <tt><i>alloc</i></tt>.</ins></td>
</tr>
<tr>
<td><ins><tt>rhs</tt> does not contain a value</ins></td>
<td><ins>destroys the contained value by calling <tt>val->T::~T()</tt></ins></td>
<td><ins>no effect</ins></td>
</tr>
</table></blockquote>
<br/><tab/><i>Returns:</i> <tt>*this</tt>.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Remarks:</i> If any exception is thrown, the result of the expression <tt>bool(*this)</tt> remains unchanged.
If an exception is thrown during the call to <tt>T</tt>'s constructor, no effect. If an exception is thrown during the call
to <tt>T</tt>'s assignment, the state of <tt>*val</tt>  is determined by the exception safety guarantee of <tt>T</tt>'s assignment.
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, U&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_assignable&lt;T&amp;, U&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, and
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>


<br/>
<br/><tt>template&lt;class U&gt; optional&amp; operator=(optional&lt;U&gt;&amp;&amp; rhs);</tt>
<br/><tab/><i>Effects:</i> See Table
<blockquote>
<table border="1">
<caption><ins>Table &mdash; <tt>optional operator=(optional&lt;U&gt;&amp;&amp;)</tt> effects</ins></caption>
<tr>
<th></th>
<th><ins><tt>*this</tt> contains a value</ins></th>
<th><ins><tt>*this</tt> does not contain a value</ins></th>
</tr>
<tr>
<td><ins><tt>rhs</tt> contains a value</ins></td>
<td><ins>assigns <tt>*rhs</tt> to the contained value</ins></td>
<td><ins>initializes the contained value with <tt>*rhs</tt>.
If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, initialization is done by uses-allocator construction 
with allocator <tt><i>alloc</i></tt> .</ins></td>
</tr>
<tr>
<td><ins><tt>rhs</tt> does not contain a value</ins></td>
<td><ins>destroys the contained value by calling <tt>val->T::~T()</tt></ins></td>
<td><ins>no effect</ins></td>
</tr>
</table></blockquote>
<br/><tab/><i>Returns:</i> <tt>*this</tt>.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Remarks:</i> If any exception is thrown, the result of the expression <tt>bool(*this)</tt> remains unchanged.
If an exception is thrown during the call to <tt>T</tt>'s move constructor, the state of <tt>*rhs.val</tt> is determined by
the exception safety guarantee of <tt>T</tt>'s move constructor. If an exception is thrown during the call to <tt>T</tt>'s move assignment,
the state of <tt>*val</tt> and <tt>*rhs.val</tt> is determined by the exception safety guarantee of <tt>T</tt>'s move assignment.
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_same&lt;T,U&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_assignable&lt;T&amp;, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const U&amp;, T&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, and
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>

<br/>
<br/><tt>template&lt;class U&gt; optional&amp; operator=(std::optional&lt;U&gt;&amp;&amp; rhs);</tt>
<br/><tab/><i>Effects:</i> See Table
<blockquote>
<table border="1">
<caption><ins>Table &mdash; <tt>optional operator=(std::optional&lt;U&gt;&amp;&amp;)</tt> effects</ins></caption>
<tr>
<th></th>
<th><ins><tt>*this</tt> contains a value</ins></th>
<th><ins><tt>*this</tt> does not contain a value</ins></th>
</tr>
<tr>
<td><ins><tt>rhs</tt> contains a value</ins></td>
<td><ins>assigns <tt>*rhs</tt> to the contained value</ins></td>
<td><ins>initializes the contained value with <tt>*rhs</tt>.
If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, initialization is done by uses-allocator construction 
with allocator <tt><i>alloc</i></tt> </ins></td>
</tr>
<tr>
<td><ins><tt>rhs</tt> does not contain a value</ins></td>
<td><ins>destroys the contained value by calling <tt>val->T::~T()</tt></ins></td>
<td><ins>no effect</ins></td>
</tr>
</table></blockquote>
<br/><tab/><i>Returns:</i> <tt>*this</tt>.
<br/><tab/><i>Ensures:</i> <tt>bool(rhs) == bool(*this)</tt>.
<br/><tab/><i>Remarks:</i> If any exception is thrown, the result of the expression <tt>bool(*this)</tt> remains unchanged.
If an exception is thrown during the call to <tt>T</tt>'s constructor, the state of <tt>*rhs.val</tt> is determined by the exception
safety guarantee of <tt>T</tt>'s constructor. If an exception is thrown during the call to <tt>T</tt>'s assignment,
the state of <tt>*val</tt> and <tt>*rhs.val</tt> is determined by the exception safety guarantee of <tt>T</tt>'s assignment.
<br/><tab/><i>Mandates:</i>
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_assignable&lt;T&amp;, const U&amp;&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­constructible_­v&lt;T, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const U&amp;, T&gt;</tt> is <tt>true</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const std::optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_­convertible_­v&lt;const optional&lt;U&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const std::optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&gt;</tt> is <tt>false</tt>,
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const std::optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>, and
<br/><tab2/> - <tt>is_assignable_v&lt;T&amp;, const optional&lt;U&gt;&amp;&amp;&gt;</tt> is <tt>false</tt>


<br/>
<br/><code>  template&lt;class... Args&gt;> T&amp; emplace(Args&amp;&amp;...);</code>
<br/><tab/><i>Constraints:</i> <tt>is_­constructible_­v&lt;T, Args&amp;&amp;...&gt; </tt>is true.
<br/><tab/><i>Effects:</i> Calls <tt>*this = nullopt</tt>. Then initializes the contained value 
with <tt>std​::​forward&lt;Args&gt;(args)....</tt>. If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, initialization is done by uses-allocator construction 
with allocator <tt><i>alloc</i></tt>.
<br/><tab/><i>Ensures:</i> <tt>*this</tt> contains a value.
<br/><tab/><i>Returns:</i> A reference to the new contained value.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Remarks:</i>  If an exception is thrown during the call to <tt>T</tt>'s constructor,
<tt>*this</tt> does not contain a value, and the previous <tt>*val</tt> (if any) has been destroyed.


<br/>
<br/><code>    template&lt;class U, class... Args&gt; T&amp; emplace(initializer_list&lt;U&gt;, Args&amp;&amp;...);</code>
<br/><tab/><i>Constraints:</i> <tt>is_­constructible_­v&lt;T, initializer_­list&lt;U&gt;&amp;, Args&amp;&amp;...&gt; </tt>is true.
<br/><tab/><i>Effects:</i> Calls <tt>*this = nullopt</tt>. Then initializes the contained value 
with <tt>il</tt> and <tt> std​::​forward&lt;Args&gt;(args)....</tt>. If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, initialization is done by uses-allocator construction 
with allocator <tt><i>alloc</i></tt>.
<br/><tab/><i>Ensures:</i> <tt>*this</tt> contains a value.
<br/><tab/><i>Returns:</i> A reference to the new contained value.
<br/><tab/><i>Throws:</i> Any exception thrown by the selected constructor of <tt>T</tt>.
<br/><tab/><i>Remarks:</i>  If an exception is thrown during the call to <tt>T</tt>'s constructor,
<tt>*this</tt> does not contain a value, and the previous <tt>*val</tt> (if any) has been destroyed.
</ins></blockquote>


<p><h4><ins> Swap [pmroptional.swap]</ins></h4></p>
<blockquote><ins>

<br/><tt>void swap(optional&amp; rhs) noexcept(<i>see below</i>);</tt>
<br/><tab/><i>Constraints:</i> Lvalues of type <tt>T</tt> shall be swappable and <tt>is_­move_­constructible_­v&lt;T&gt;</tt> is <tt>true</tt>.
<br/><tab/><i>Expects:</i>If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, <tt>a.get_allocator() == b.get_allocator()</tt>.
<br/><tab/><i>Effects:</i> See Table x
<br/><tab/><i>Throws:</i> Any exceptions thrown by the operations in the relevant part of Table x.
<br/><tab/><i>Remarks:</i> The expression inside <tt>noexcept</tt> is equivalent to:
<tt>is_nothrow_move_constructible_v&lt;T&gt; &and;&and; is_nothrow_swappable_v&lt;T&gt;</tt>
If any exception is thrown, the results of the expressions <tt>bool(*this)</tt> and <tt>bool(rhs)</tt> remain unchanged.
If an exception is thrown during the call to function <tt>swap</tt>, the state of <tt>*val</tt> and <tt>*rhs.val</tt> is determined
by the exception safety guarantee of <tt>swap</tt> for lvalues of <tt>T</tt>. If an exception is thrown during the call to
<tt>T</tt>’s move constructor, the state of tt>*val</tt>  and <tt>*rhs.val</tt> is determined by the exception safety guarantee
of <tt>T</tt>’s move constructor.
<blockquote><table border="1">
<caption><ins>Table x &mdash; <tt>swap(optional&amp;)</tt> effects</ins></caption>
<tr>
<th></th>
<th><ins><tt>*this</tt> contains a value</ins></th>
<th><ins><tt>*this</tt> does not contain a value</ins></th>
</tr>
<tr>
<td><ins><tt>rhs</tt> contains a value</ins></td>
<td><ins>calls <tt>swap(*(*this), *rhs)</tt></ins></td>
<td><ins>initializes the contained value with
<tt>std​::​move(*rhs)</tt> as the constructor argument, followed by <tt>rhs.val->T​::​~T()</tt>;
If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, initialization is done by uses-allocator construction 
with allocator <tt><i>alloc</i></tt>.
Postcondition is that <tt>*this</tt> contains a value and <tt>rhs</tt> does not contain a value</ins></td>
</tr>
<tr>
<td><ins><tt>rhs</tt> does not contain a value</ins></td>
<td><ins>initializes the contained value with
<tt>std​::​move(*(*this))</tt> as the constructor argument, followed by <tt>val->T​::​~T()</tt>; 
If <tt>uses-poly-alloc</tt>
 is <tt>true</tt>, initialization is done by uses-allocator construction 
with allocator <tt><i>alloc</i></tt>.
Postcondition is that <tt>*this</tt> does not contain a value and <tt>rhs</tt> contains a value</ins></tt></ins></td>
<td><ins>no effect</ins></td>
</tr>
</table></blockquote>
<br/><tab/><i>Throws:</i> Any exceptions thrown by the operations in the relevant part of Table x.
</ins></blockquote>


<p><h4><ins> Observers [pmroptional.observe]</ins></h4></p>
<blockquote><ins>


<br/><tt>const T* operator-&gt;() const;</tt>
<br/><tt>T* operator-&gt;();</tt>
<br/><tab/><i>Expects:</i> <tt>*this</tt> contains a value.
<br/><tab/><i>Returns:</i> <tt>val</tt>.
<br/><tab/><i>Throws:</i> Nothing.

<br/>
<br/><tt>const T&amp; operator*() const&amp;;</tt>
<br/><tt>T&amp; operator*() &amp;;();</tt>
<br/><tab/><i>Expects:</i> <tt>*this</tt> contains a value.
<br/><tab/><i>Returns:</i> <tt>*val</tt>.
<br/><tab/><i>Throws:</i> Nothing.

<br/>
<br/><tt>T&amp;&amp; operator*() &amp;&amp;;</tt>
<br/><tt>const T&amp;&amp; operator*() const&amp;&amp;; &amp;;();</tt>
<br/><tab/><i>Expects:</i> <tt>*this</tt> contains a value.
<br/><tab/><i>Effects:</i> Equivalent to:<tt> return std​::​move(*val);</tt>


<br/>
<br/><tt>explicit operator bool() const noexcept;</tt>
<br/><tab/><i>Returns:</i> <tt>true</tt> if and only if <tt*this></tt> contains a value.

<br/>
<br/><tt>bool has_value() const noexcept;</tt>
<br/><tab/><i>Returns:</i> <tt>true</tt> if and only if <tt*this></tt> contains a value.

<br/>
<br/><tt>const T&amp; value() const&amp;;</tt>
<br/><tt>T&amp; value() &amp;;</tt>
<br/><tab/><i>Effects:</i> Equivalent to:
<br/><tab2/><tt>return bool(*this) ? *val : throw bad_optional_access();</tt>

<br/>
<br/><tt>T&amp;&amp; value() &amp;&amp;;</tt>
<br/><tt> const T&amp;&amp; value() const&amp;&amp;;</tt>
<br/><tab/><i>Effects:</i> Equivalent to:
<br/><tab2/><tt>return bool(*this) ? std::move(*val) : throw bad_optional_access();</tt>

<br/>
<br/><tt>template&lt;class U&gt; T value_or(U&amp;&amp; v) const&amp;;</tt>
<br/><tab/><i>Effects:</i> Equivalent to:
<br/><tab2/><tt>return bool(*this) ? **this : static_cast&lt;T&gt;(std::forward&lt;U&gt;(v));</tt>
<br/><tab/><i>Remarks:</i> If <tt>is_­copy_­constructible_­v&lt;T&gt;
&& is_­convertible_­v&lt;U&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
the program is ill-formed.

<br/>
<br/><tt>template&lt;class U&gt; T value_or(U&amp;&amp; v) &amp;&amp;;</tt>
<br/><tab/><i>Effects:</i> Equivalent to:
<br/><tab2/><tt>return bool(*this) ? std::move(**this) : static_cast&lt;T&gt;(std::forward&lt;U&gt;(v));</tt>
<br/><tab/><i>Remarks:</i> If <tt>is_­move_­constructible_­v&lt;T&gt;
&& is_­convertible_­v&lt;U&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
the program is ill-formed.


<br/>
<br/><tt>    template&lt;class U&gt; T value_or(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp; a, U&amp;&amp; v) const&amp;;</tt>tt>
<br/><tab/><i>Constraints:</i> <tt>uses_allocator&lt;T,polymorphic_allocator&lt;&gt;&gt;</tt> is true;
<br/><tab/><i>Effects:</i> if <tt>*this</tt> contains a value, returns an object of type <tt>T</tt> initialized by
uses-allocator construction with allocator <tt>a</tt> and <tt>**this</tt> as the constructor argument.
Otherwise, returns an object of type <tt>T</tt> initialized by
uses-allocator construction with allocator <tt>a</tt> and <tt>std::forward&lt;U&gt;(v)</tt> as the constructor argument.
<br/><tab/><i>Remarks:</i> If <tt>is_­copy_­constructible_­v&lt;T&gt;
&& is_­convertible_­v&lt;U&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
the program is ill-formed.

<br/>
<br/><tt>    template&lt;class U&gt; T value_or(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp; a, U&amp;&amp; v) &amp;&amp;;</tt>
<br/><tab/><i>Constraints:</i> <tt>uses_allocator&lt;T,polymorphic_allocator&lt;&gt;&gt;</tt> is true;
<br/><tab/><i>Effects:</i> if <tt>*this</tt> contains a value, returns an object of type <tt>T</tt> initialized by
uses-allocator construction with allocator <tt>a</tt> and <tt>std::move(**this)</tt> as the constructor argument.
Otherwise, returns an object of type <tt>T</tt> initialized by
uses-allocator construction with allocator <tt>a</tt> and <tt>std::forward&lt;U&gt;(v)</tt> as the constructor argument.
<br/><tab/><i>Remarks:</i> If <tt>is_­copy_­constructible_­v&lt;T&gt;
&& is_­convertible_­v&lt;U&amp;&amp;, T&gt;</tt> is <tt>false</tt>,
the program is ill-formed.

<br/>
<br/><tt>allocator_type get_allocator() const noexcept;</tt>
<br/><tab/><i>Constraints:</i> <tt>uses_allocator&lt;T,polymorphic_allocator&lt;&gt;&gt;</tt> is true;
<br/><tab/><i>Returns:</i> <tt><i>alloc</i></tt>.
<br/><tab/><i>Throws:</i> nothing.


</ins></blockquote>


<p><h4><ins> Modifiers [pmroptional.mod]</ins></h4></p>
<blockquote><ins>

<br/><tt>void reset() noexcept;</tt>
<br/><tab/><i>Effects:</i> If <tt>*this</tt> contains a value, calls <tt>val->T​::​~T()</tt> to destroy the contained value; otherwise no effect.
<br/><tab/><i>Ensures:</i> <tt>*this</tt> does not contain a value.

</ins></blockquote>
<p><h4><ins> Allocator-related traits [pmroptional.traits]</ins></h4></p>
<blockquote><ins>
<br/><tt>    template&ltclass T&gt;</tt>
<br/><tt>   struct uses_allocator&ltT, polymorphic_allocator&lt;&gt;&gt; : 
<br/><tab/><tt>   uses_allocator&ltT,  polymorphic_allocator&lt;&gt;&gt; { };</tt>

</ins></blockquote>

<p><h3><ins> Relational operators [pmroptional.relops]</ins></h3></p>
<blockquote><ins>
<tt>
<br/><tab/>   template&lt;class T, class U&gt; bool operator==(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator==(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator==(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x == *y</tt> shall be well-formed and its result shall be convertible to 
<tt>bool</tt>. [ <i>Note:</i> <tt>T</tt> need not be <tt>Cpp17EqualityComparable</tt>. — <i>end note</i> ]
<br/><tab/><i>Returns:</i> If <tt>bool(x) != bool(y)</tt>, <tt>false</tt>; otherwise if <tt>bool(x) == false</tt>, <tt>true</tt>; otherwise <tt>*x == *y</tt>.


<br/>
<tt>
<br/><tab/>   template&lt;class T, class U&gt; bool operator!=(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt;bool operator!=(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator!=(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x != *y</tt> shall be well-formed and its result shall be convertible to 
<tt>bool</tt>. 
<br/><tab/><i>Returns:</i> If <tt>bool(x) != bool(y)</tt>, <tt>true</tt>; otherwise if <tt>bool(x) == false</tt>, <tt>false</tt>; 
otherwise <tt>*x != *y</tt>.

<br/>
<tt>
<br/><tab/>   template&lt;class T, class U&gt; bool operator&lt;(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&lt;(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&lt;(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x &lt; *y</tt> shall be well-formed and its result shall be convertible to 
<tt>bool</tt>. 
<br/><tab/><i>Returns:</i> If <tt>!y</tt>, <tt>false</tt>; otherwise if <tt>!x</tt>, <tt>true</tt>; 
otherwise <tt>*x &lt; *y</tt>.



<br/>
<tt>
<br/><tab/>   template&lt;class T, class U&gt; bool operator&gt;(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&gt;(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&gt;(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x &gt; *y</tt> shall be well-formed and its result shall be convertible to 
<tt>bool</tt>. 
<br/><tab/><i>Returns:</i> If <tt>!x</tt>, <tt>false</tt>; otherwise if <tt>!y</tt>, <tt>true</tt>; 
otherwise <tt>*x &gt; *y</tt>.


<br/>
<tt>
<br/><tab/>   template&lt;class T, class U&gt; bool operator&lt;=(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&lt;=(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&lt;=(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x &lt;= *y</tt> shall be well-formed and its result shall be convertible to 
<tt>bool</tt>. 
<br/><tab/><i>Returns:</i> If <tt>!x</tt>, <tt>true</tt>; otherwise if <tt>!y</tt>, <tt>false</tt>; 
otherwise <tt>*x &lt;= *y</tt>.


<br/>
<tt>
<br/><tab/>   template&lt;class T, class U&gt; bool operator&t;=(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&gt;=(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, class U&gt; bool operator&gt;=(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x &gt;= *y</tt> shall be well-formed and its result shall be convertible to 
<tt>bool</tt>. 
<br/><tab/><i>Returns:</i> If <tt>!y</tt>, <tt>true</tt>; otherwise if <tt>!x</tt>, <tt>false</tt>; 
otherwise <tt>*x &gt;= *y</tt>.


<br/>
<tt>
<br/><tab/>   template&lt;class T, three_way_comparable_with&lt;T&gt; U&gt;
<br/><tab2/>	compare_three_way_result_t&lt;T,U&gt;
<br/><tab/><tab2/>      operator&lt;=&gt;(const optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, three_way_comparable_with&lt;T&gt; U&gt;
<br/><tab2/>	compare_three_way_result_t&lt;T,U&gt;
<br/><tab/><tab2/>      operator&lt;=&gt;(const optional&lt;T&gt;&amp;, const std::optional&lt;U&gt;&amp;);
<br/><tab/>   template&lt;class T, three_way_comparable_with&lt;T&gt; U&gt;
<br/><tab2/>	compare_three_way_result_t&lt;T,U&gt;
<br/><tab/><tab2/>      operator&lt;=&gt;(const std::optional&lt;T&gt;&amp;, const optional&lt;U&gt;&amp;);
</tt>
<br/><tab/><i>Returns:</i> If <tt>x &amp;&amp; y</tt>, <tt>*x &lt;=&gt; *y</tt>; otherwise <tt>bool(x) &lt;=&gt; bool(y)</tt>.
</ins></blockquote>

<p><h3><ins> Comparison with nullopt [pmroptional.nullops]</ins></h3></p>
<blockquote><ins>
<br/><tab/><tt>   template&lt;class T&gt; bool operator==(const optional&lt;T&gt;&amp;, nullopt_t) noexcept;</tt>
<br/><tab/><i>Returns:</i> <tt>!x</tt>.

<br/>
<br/><tab/><tt>   template&lt;class T&gt; strong_ordering operator&lt;=&gt;(const optional&lt;T&gt;&amp;, nullopt_t) noexcept;</tt>
<br/><tab/><i>Returns:</i> <tt>bool(x) &lt;=&gt; false</tt>.
</ins></blockquote>


<p><h3><ins> Comparison with <tt>T</tt> [pmroptional.comp.with.t]</ins></h3></p>
<blockquote><ins>

<br/><tab/><tt>    template&lt;class T, class U&gt; bool operator==(const optional&lt;T&gt;&amp; x, const U&amp; v);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x == v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>.
[ <tt>Note:</tt> <tt>T</tt> need not be <tt>Cpp17EqualityComparable</tt>. — <tt>end note </tt>]
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(x) ? *x == v : false;</tt>


<br/>
<br/><tab/><tt>    template&lt;class T, class U&gt; bool operator==(const T&amp; t, const optional&lt;U&gt;&amp; v);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>x == *v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>. 
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(v) ? x == *v : false;</tt>

<br/>
<br/><tab/><tt>    template&lt;class T, class U&gt; bool operator!=(const optional&lt;T&gt;&amp; u, const U&amp; v);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x != v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>.
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(x) ? *x != v : true;</tt>

<br/>
<br/><tab/><tt>    template&lt;class T, class U&gt; bool operator!=(const T&amp; t, const optional&lt;U&gt;&amp; v);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>x != *v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>.
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(v) ? x != *v : true;</tt>


<br/>
<br/><tab/><tt>    template&lt;class T, class U&gt; bool operator&lt;(const optional&lt;T&gt;&amp;, const U&amp;);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x &lt; v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>.
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(x) ? *x &lt; v : true;</tt>


<br/>
<br/><tab/><tt>    template&lt;class T, class U&gt; bool operator&lt;(const T&amp; t, const optional&lt;U&gt;&amp; v);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>x &lt; *v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>.
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(v) ? x &lt; *v : false;</tt>


<br/>
<br/><tab/><tt>    template&lt;class T, class U&gt; bool operator&gt;(const optional&lt;T&gt;&amp;, const U&amp;);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x &gt; v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>.
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(x) ? *x &gt; v : false;</tt>


<br/>
<br/><tab/><tt>    template&lt;class T, class U&gt; bool operator&gt;(const T&amp; t, const optional&lt;U&gt;&amp; v);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>x &gt; *v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>.
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(v) ? x &gt; *v : true;</tt>


<br/>
<br/><tab/><tt>    template&lt;class T, class U&gt; bool operator&lt;=(const optional&lt;T&gt;&amp;, const U&amp;);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x &lt;= v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>.
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(x) ? *x &lt;= v : true;</tt>


<br/>
<br/><tab/><tt>    template&lt;class T, class U&gt; bool operator&lt;=(const T&amp; t, const optional&lt;U&gt;&amp; v);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>x &lt;= *v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>.
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(v) ? x &lt;= *v : false;</tt>


<br/>
<br/><tab/><tt>    template&lt;class T, class U&gt; bool operator&gt;=(const optional&lt;T&gt;&amp;, const U&amp;);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>*x &gt;= v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>.
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(x) ? *x &gt;= v : false;</tt>


<br/>
<br/><tab/> <tt>   template&lt;class T, class U&gt; bool operator&gt;=(const T&amp; t, const optional&lt;U&gt;&amp; v);</tt>
<br/><tab/><i>Mandates:</i> The expression <tt>x &gt;= *v</tt> shall be well-formed and its result shall be convertible to <tt>bool</tt>.
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(v) ? x &gt;= *v : true;</tt>


<br/>
<br/><tab/><tt>    template&lt;class T, three_way_comparable_with&lt;T&gt; U&gt;
<br/><tab2/>	compare_three_way_result_t&lt;T,U&gt;
<br/><tab/><tab2/>      operator&lt;=&gt;(const optional&lt;T&gt;&amp; x, const U&amp;v);</tt>
<br/><tab/><i>Effects: </i> Equivalent to: <tt>return bool(x) ? *x &gt;=&lt; v : strong_­ordering​::​less ;</tt>

</ins></blockquote>

<p><h3><ins>  Specialized algorithms [pmroptional.specalg]</ins></h3></p>
<blockquote><ins>

<br/><tab/><tt>   template&lt;class T&gt; void swap(optional&lt;T&gt;&amp; x, optional&lt;T&gt;&amp; y)</tt>
<br/><tab/><i>Effects: </i> if <tt>x.get_allocator() == y.get_allocator()</tt>, calls <tt> x.swap(y)</tt>. Otherwise equvivalent to
<tt>
<br/><tab2/>std::pmr::optional futureX(allocator_arg_t,x.get_allocator(),y);
<br/><tab2/>std::pmr::optional futureY(allocator_arg_t,y.get_allocator(),x);
<br/><tab2/>futureX.swap(x);
<br/><tab2/>futureY.swap(y);

</tt>


<br/>
<br/><tab/><tt>   template&lt;class T&gt; constexpr optional&lt;decay_­t&lt;T&gt;&gt; make_optional(T&amp;&amp;);</tt>
<br/><tab/><i>Returns: </i> <tt>optional&lt;decay_­t&lt;T&gt;&gt;(std​::​forward&lt;T&gt;(v)).</tt>
<br/><tab/><i>Remarks: </i> Specialization of this function template shall be a constexpr function if  
<tt>uses-poly-alloc::value</tt> is <tt>false</tt>. 

<br/>
<br/><tab/><tt>   template&lt;class T&gt; constexpr optional&lt;T&gt; make_optional();</tt>
<br/><tab/><i>Effects: </i> Equivalent to: <tt> return optional&lt;T&gt(in_­place).</tt>
<br/><tab/><i>Remarks: </i> Specialization of this function template shall be a constexpr function if  
<tt>uses-poly-alloc::value</tt> is <tt>false</tt>.

<br/>
<br/><tab/><tt>   template&lt;class T, class Arg0, class... Args&gt constexpr 
                    optional&lt;T&gt; make_optional(Arg0&amp;&amp; arg0, Args&amp;&amp;... args);</tt>
<br/><tab/><i>Effects: </i> Equivalent to: <tt> return optional&lt;T&gt(in_­place, std​::​forward&lt;Arg0&gt;(arg0), std​::​forward&lt;Args&gt;(args)...).</tt>
<br/><tab/><i>Constraints: </i><tt> !is_same&lt; typename remove_cvref_t&lt;ARG0&gt;, allocator_arg_t&gt;</tt>
<br/><tab/><i>Remarks: </i> Specialization of this function template shall be a constexpr function if  
<tt>uses-poly-alloc::value</tt> is <tt>false</tt>.

<br/>
<br/><tab/><tt>   template&lt;class T, class... Args&gt constexpr optional&lt;T&gt; make_optional(Args&amp;&amp;... args);</tt>
<br/><tab/><i>Effects: </i> Equivalent to: <tt> return optional&lt;T&gt(in_­place, std​::​forward&lt;Args&gt;(args)...).</tt>
<br/><tab/><i>Remarks: </i> Specialization of this function template shall be a constexpr function if  
<tt>uses-poly-alloc::value</tt> is <tt>false</tt>.

<br/>
<br/><tab/><tt>   template&lt;class T, class U, class... Args> optional&lt;T&gt; </tt>
<br/><tab2/><tt>  constexpr make_optional(initializer_list&lt;U&gt; il, Args&amp;&amp;... args);</tt>
<br/><tab/><i>Effects: </i> Equivalent to: <tt> return optional&lt;T&gt(in_­place, il, std​::​forward&lt;Args&gt;(args)...).</tt>
<br/><tab/><i>Remarks: </i> Specialization of this function template shall be a constexpr function if  
<tt>uses-poly-alloc::value</tt> is <tt>false</tt>.

<br/>
<br/><tab/><tt>  template&lt;class T, optional&lt;decay_­t&lt;T&gt;&gt; </tt>
<br/><tab2/><tt>  make_optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp; a, T&amp;&amp;);</tt>
<br/><tab/><i>Mandates:</i> <tt>uses_allocator&lt;T,polymorphic_allocator&lt;&gt;&gt;</tt> is true;
<br/><tab/><i>Returns: </i> <tt>optional&lt;decay_­t&lt;T&gt;&gt;(allocator_arg, a, in_place, std​::​forward&lt;T&gt;(v)).</tt>

<br/>
<br/><tab/><tt>   template&lt;class T, class... Args> optional&lt;T&gt; </tt>
<br/><tab2/><tt>  make_optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp; a, Args&amp;&amp;... args);</tt>
<br/><tab/><i>Mandates:</i> <tt>uses_allocator&lt;T,polymorphic_allocator&lt;&gt;&gt;</tt> is true;
<br/><tab/><i>Effects: </i> Equivalent to: <tt> return optional&lt;T&gt(allocator_arg, a, in_place, std​::​forward&lt;Args&gt;(args)...).</tt>

<br/>
<br/><tab/><tt>   template&lt;class T, class U, class... Args> optional&lt;T&gt;</tt>
<br/><tab2/><tt>  make_optional(allocator_arg_t, const polymorphic_allocator&lt;&gt;&amp; a, initializer_list&lt;U&gt; il, Args&amp;&amp;... args);</tt>
<br/><tab/><i>Mandates:</i> <tt>uses_allocator&lt;T,polymorphic_allocator&lt;&gt;&gt;</tt> is true;
<br/><tab/><i>Effects: </i> Equivalent to: <tt> return optional&lt;T&gt(allocator_arg, a, in_place, il, std​::​forward&lt;Args&gt;(args)...).</tt>

</ins></blockquote>

<p><h3><ins>  Hash support [pmroptional.hash]</ins></h3></p>
<blockquote><ins>
<br/><tab/><tt>   template&lt;class T&gt; struct hash&lt;optional&lt;T&gt;&gt;;</tt>
<br/><tab/> The specialization <tt>hash&lt;optional&lt;T&gt;&gt;</tt> is enabled ([unord.hash]) if and only if 
<tt>hash&lt;remove_­const_­t&lt;T&gt;&gt;</tt> is enabled. When enabled, for an object <tt>o</tt> of type <tt>optional&lt;T&gt;</tt>, 
if <tt>bool(o) == true</tt>, then <tt>hash&lt;optional&lt;T&gt;&gt;()(o)</tt> shall evaluate to the 
same value as <tt>hash&lt;remove_­const_­t&lt;T&gt;&gt;()(*o)</tt>; otherwise it evaluates to an unspecified value. 
The member functions are not guaranteed to be <tt>noexcept</tt>.
</ins></blockquote>

</body>
</html> 
