<h1
id="add-missing-constructors-and-assignment-for-indirect-and-polymorphic">Add
missing constructors and assignment for <code>indirect</code> and
<code>polymorphic</code></h1>
<!-- markdownlint-disable MD029 -->
<p>ISO/IEC JTC1 SC22 WG21 Programming Language C++</p>
<p>P3152R0</p>
<p>Working Group: Library Evolution, Library</p>
<p>Date: 2024-09-30</p>
<p><em>Jonathan Coe &lt;<a href="mailto:jonathanbcoe@gmail.com"
class="email">jonathanbcoe@gmail.com</a>&gt;</em></p>
<p><em>Antony Peacock &lt;<a href="mailto:ant.peacock@gmail.com"
class="email">ant.peacock@gmail.com</a>&gt;</em></p>
<p><em>Sean Parent &lt;<a href="mailto:sparent@adobe.com"
class="email">sparent@adobe.com</a>&gt;</em></p>
<h2 id="contents">Contents</h2>
<ul>
<li><a href="#introduction">Introduction</a></li>
<li><a href="#single-argument-constructors">Single-argument
constructors</a></li>
<li><a href="#perfect-forwarded-assignment">Perfect-forwarded
assignment</a></li>
<li><a href="#technical-specifications">Technical
specifications</a></li>
<li><a href="#reference-implementation">Reference
implementation</a></li>
<li><a href="#acknowledgements">Acknowledgements</a></li>
<li><a href="#references">References</a></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>New vocabulary types <code>indirect</code> and
<code>polymorphic</code> for composite class design are proposed in
P3019 [1]. Based on recommendations from LEWG, we follow up this work by
adding support for single-argument construction, initializer-list
construction and perfect-forwarded assignment to <code>indirect</code>
and <code>polymorphic</code> where appropriate.</p>
<p>The design changes to P3019 are presented in this paper so that they
can be reviewed by the Library Evolution Working Group in isolation.
Changes to formal wording from this paper have been incorporated into
P3019R9 so that wording can be reviewed in its entirety by the Library
Wording Group.</p>
<h2 id="additional-constructors">Additional constructors</h2>
<h3 id="single-argument-constructors">Single-argument constructors</h3>
<p>In line with <code>optional</code> and <code>variant</code>, we add
single-argument constructors to both <code>indirect</code> and
<code>polymorphic</code> so they can be constructed from single values
without the need to use <code>in_place</code> or
<code>in_place_type</code>. As <code>indirect</code> and
<code>polymorphic</code> are allocator-aware types, we also provide
allocator-extended versions of these constructors, in line with those
from <code>basic_optional</code> [2] and existing constructors from
<code>indirect</code> and <code>polymorphic</code>.</p>
<p>As <code>indirect</code> and <code>polymorphic</code> will use
dynamic memory, the single-argument constructors are marked as explicit,
the same as other constructors in <code>indirect</code> and
<code>polymorphic</code>.</p>
<h3 id="initializer-list-constructors">Initializer-list
constructors</h3>
<p>We add initializer-list constructors to both <code>indirect</code>
and <code>polymorphic</code> in line with those in <code>optional</code>
and <code>variant</code>. As <code>indirect</code> and
<code>polymorphic</code> are allocator-aware types, we provide
allocator-extended versions of these constructors, in line with those
from <code>basic_optional</code> [2] and existing constructors from
<code>indirect</code> and <code>polymorphic</code>.</p>
<p>As <code>indirect</code> and <code>polymorphic</code> will use
dynamic memory, the initializer-list constructors are marked as
explicit, the same as other constructors in <code>indirect</code> and
<code>polymorphic</code>.</p>
<h2 id="perfect-forwarded-assignment">Perfect-forwarded assignment</h2>
<h3 id="perfect-forwarded-assignment-for-indirect">Perfect-forwarded
assignment for <code>indirect</code></h3>
<p>We add a perfect-forwarded assignment operator for
<code>indirect</code> in line with those from <code>optional</code> and
<code>variant</code>.</p>
<div class="sourceCode" id="cb1"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">=</span>T<span class="op">&gt;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">constexpr</span> optional<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span>U<span class="op">&amp;&amp;</span> u<span class="op">);</span></span></code></pre></div>
<p>When assigning to an <code>indirect</code>, there is potential for
optimisation if there is an existing owned object to be assigned to:</p>
<div class="sourceCode" id="cb2"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a>indirect<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> i<span class="op">;</span></span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>foo<span class="op">(</span>i<span class="op">);</span>  <span class="co">// could move from `i`.</span></span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a><span class="cf">if</span> <span class="op">(!</span>i<span class="op">.</span>valueless_after_move<span class="op">())</span> <span class="op">{</span></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a>  <span class="op">*</span>i <span class="op">=</span> <span class="dv">5</span><span class="op">;</span></span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a>  i <span class="op">=</span> indirect<span class="op">(</span><span class="dv">5</span><span class="op">);</span></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
<p>With value assignment, handling the valueless state and potentially
creating a new indirect object is done within the value assignment. The
code below is equivalent to the code above:</p>
<div class="sourceCode" id="cb3"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>indirect<span class="op">&lt;</span><span class="dt">int</span><span class="op">&gt;</span> i<span class="op">;</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>foo<span class="op">(</span>i<span class="op">);</span> <span class="co">// could move from `i`.</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a>i <span class="op">=</span> <span class="dv">5</span><span class="op">;</span></span></code></pre></div>
<h3 id="perfect-forwarded-assignment-for-polymorphic">Perfect-forwarded
assignment for <code>polymorphic</code></h3>
<p>There is no perfect-forwarded assignment for <code>polymorphic</code>
as type information is erased. There is no optimisation opportunity to
be made as a new object will need creating regardless of whether the
target of assignment is valueless or not.</p>
<h2 id="technical-specifications">Technical specifications</h2>
<p>Here we list additions to the technical specifications in P3019 [1]
to include the constructors and assignment operators discussed
above.</p>
<h3 id="x.y-class-template-indirect-indirect">X.Y Class template
indirect [indirect]</h3>
<h4 id="x.y.1-class-template-indirect-synopsis-indirect.syn">X.Y.1 Class
template indirect synopsis [indirect.syn]</h4>
<div class="sourceCode" id="cb4"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">,</span> <span class="kw">class</span> Allocator <span class="op">=</span> allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> indirect <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ... existing constructors</span></span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-6"><a href="#cb4-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">=</span>T<span class="op">&gt;</span></span>
<span id="cb4-7"><a href="#cb4-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> indirect<span class="op">(</span>U<span class="op">&amp;&amp;</span> u<span class="op">);</span></span>
<span id="cb4-8"><a href="#cb4-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-9"><a href="#cb4-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">&gt;</span></span>
<span id="cb4-10"><a href="#cb4-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> indirect<span class="op">(</span><span class="dt">allocator_arg_t</span><span class="op">,</span> <span class="at">const</span> Allocator<span class="op">&amp;</span> a<span class="op">,</span> U<span class="op">&amp;&amp;</span> u<span class="op">);</span></span>
<span id="cb4-11"><a href="#cb4-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-12"><a href="#cb4-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">,</span> <span class="kw">class</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb4-13"><a href="#cb4-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> indirect<span class="op">(</span><span class="dt">in_place_t</span><span class="op">,</span> initializer_list<span class="op">&lt;</span>I<span class="op">&gt;</span> ilist<span class="op">,</span></span>
<span id="cb4-14"><a href="#cb4-14" aria-hidden="true" tabindex="-1"></a>                              Us<span class="op">&amp;&amp;...</span> us<span class="op">);</span></span>
<span id="cb4-15"><a href="#cb4-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-16"><a href="#cb4-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> U<span class="op">,</span> <span class="kw">class</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb4-17"><a href="#cb4-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> indirect<span class="op">(</span><span class="dt">allocator_arg_t</span><span class="op">,</span> <span class="at">const</span> Allocator<span class="op">&amp;</span> a<span class="op">,</span></span>
<span id="cb4-18"><a href="#cb4-18" aria-hidden="true" tabindex="-1"></a>                              <span class="dt">in_place_t</span><span class="op">,</span> initializer_list<span class="op">&lt;</span>I<span class="op">&gt;</span> ilist<span class="op">,</span></span>
<span id="cb4-19"><a href="#cb4-19" aria-hidden="true" tabindex="-1"></a>                              Us<span class="op">&amp;&amp;...</span> us<span class="op">);</span></span>
<span id="cb4-20"><a href="#cb4-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-21"><a href="#cb4-21" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Remaining constructors and assignment ...</span></span>
<span id="cb4-22"><a href="#cb4-22" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-23"><a href="#cb4-23" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">=</span>T<span class="op">&gt;</span></span>
<span id="cb4-24"><a href="#cb4-24" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> indirect<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span>U<span class="op">&amp;&amp;</span> u<span class="op">);</span></span>
<span id="cb4-25"><a href="#cb4-25" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-26"><a href="#cb4-26" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Remaining member functions ...</span></span>
<span id="cb4-27"><a href="#cb4-27" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<h3 id="x.y.3-constructors-indirect.ctor">X.Y.3 Constructors
[indirect.ctor]</h3>
<div class="sourceCode" id="cb5"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">=</span>T<span class="op">&gt;</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">explicit</span> <span class="kw">constexpr</span> indirect<span class="op">(</span>U<span class="op">&amp;&amp;</span> u<span class="op">);</span></span></code></pre></div>
<p>A. <em>Constraints</em>:
<code>is_same_v&lt;remove_cv_ref_t&lt;U&gt;, U&gt;</code> is
<code>true</code>. <code>is_same_v&lt;U, indirect&gt;</code> is
<code>false</code>. <code>is_same_v&lt;U, in_place_t&gt;</code> is
<code>false</code>. <code>is_constructible_v&lt;T, U&gt;</code> is
<code>true</code>. <code>is_copy_constructible_v&lt;T&gt;</code> is
<code>true</code>.
<code>is_default_constructible_v&lt;allocator_type&gt;</code> is
<code>true</code>.</p>
<p>B. <em>Mandates</em>: <code>T</code> is a complete type.</p>
<p>C. <em>Effects</em>: Constructs an owned object of type
<code>T</code> with <code>std​::​forward&lt;U&gt;(u)</code>, using the
allocator <code>alloc</code>.</p>
<div class="sourceCode" id="cb6"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">=</span>T<span class="op">&gt;</span></span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a><span class="kw">explicit</span> <span class="kw">constexpr</span> indirect<span class="op">(</span><span class="dt">allocator_arg_t</span><span class="op">,</span> <span class="at">const</span> Allocator<span class="op">&amp;</span> a<span class="op">,</span> U<span class="op">&amp;&amp;</span> u<span class="op">);</span></span></code></pre></div>
<p>D. <em>Constraints</em>:
<code>is_same_v&lt;remove_cv_ref_t&lt;U&gt;, U&gt;</code> is
<code>true</code>. <code>is_same_v&lt;U, indirect&gt;</code> is
<code>false</code>. <code>is_same_v&lt;U, in_place_t&gt;</code> is
<code>false</code>. <code>is_constructible_v&lt;T, U&gt;</code> is
<code>true</code>. <code>is_copy_constructible_v&lt;T&gt;</code> is
<code>true</code>.</p>
<p>E. <em>Mandates</em>: <code>T</code> is a complete type.</p>
<p>F. <em>Effects</em>: <code>alloc</code> is
direct-non-list-initialized with <code>a</code>. Constructs an owned
object of type <code>T</code> with
<code>std​::​forward&lt;U&gt;(u)</code>, using the allocator
<code>alloc</code>.</p>
<div class="sourceCode" id="cb7"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I<span class="op">,</span> <span class="kw">class</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="kw">explicit</span> <span class="kw">constexpr</span> indirect<span class="op">(</span><span class="dt">in_place_t</span><span class="op">,</span> initializer_list<span class="op">&lt;</span>I<span class="op">&gt;</span> ilist<span class="op">,</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>                            Us<span class="op">&amp;&amp;...</span> us<span class="op">);</span></span></code></pre></div>
<p>G. <em>Constraints</em>:
<code>is_copy_constructible_v&lt;T&gt;</code> is <code>true</code>.
<code>is_constructible_v&lt;T, initializer_list&lt;I&gt;&amp;, Us...&gt;</code>
is <code>true</code>.
<code>is_default_constructible_v&lt;allocator_type&gt;</code> is
<code>true</code>.</p>
<p>H. <em>Mandates</em>: <code>T</code> is a complete type.</p>
<p>I. <em>Effects</em>: Constructs an owned object of type
<code>T</code> with the arguments <code>ilist</code>,
<code>std​::​forward&lt;Us&gt;(us)...</code>, using the allocator
<code>alloc</code>.</p>
<div class="sourceCode" id="cb8"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span><span class="op">&lt;</span><span class="kw">class</span> I<span class="op">,</span> <span class="kw">class</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="kw">explicit</span> <span class="kw">constexpr</span> indirect<span class="op">(</span><span class="dt">allocator_arg_t</span><span class="op">,</span> <span class="at">const</span> Allocator<span class="op">&amp;</span> a<span class="op">,</span></span>
<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a>                            <span class="dt">in_place_t</span><span class="op">,</span> initializer_list<span class="op">&lt;</span>I<span class="op">&gt;</span> ilist<span class="op">,</span></span>
<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a>                            Us<span class="op">&amp;&amp;...</span> us<span class="op">);</span></span></code></pre></div>
<p>J. <em>Constraints</em>:
<code>is_copy_constructible_v&lt;T&gt;</code> is <code>true</code>.
<code>is_constructible_v&lt;T, initializer_list&lt;I&gt;&amp;, Us...&gt;</code>
is <code>true</code>.</p>
<p>K. <em>Mandates</em>: <code>T</code> is a complete type.</p>
<p>L. <em>Effects</em>: <code>alloc</code> is
direct-non-list-initialized with <code>a</code>. Constructs an owned
object of type <code>T</code> with the arguments <code>ilist</code>,
<code>std​::​forward&lt;Us&gt;(us)...</code>, using the allocator
<code>alloc</code>.</p>
<h3 id="x.y.5-assignment-indirect.assign">X.Y.5 Assignment
[indirect.assign]</h3>
<div class="sourceCode" id="cb9"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">=</span>T<span class="op">&gt;</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>  <span class="kw">constexpr</span> indirect<span class="op">&amp;</span> <span class="kw">operator</span><span class="op">=(</span>U<span class="op">&amp;&amp;</span> u<span class="op">);</span></span></code></pre></div>
<p>A. <em>Constraints</em>:
<code>is_same_v&lt;remove_cvref_t&lt;U&gt;, indirect&gt;</code> is
<code>false</code>. <code>is_constructible_v&lt;T, U&gt;</code> is
<code>true</code>. <code>is_assignable_v&lt;T&amp;,U&gt;</code> is
<code>true</code>.</p>
<p>B. <em>Mandates</em>: <code>T</code> is a complete type.</p>
<p>C. <em>Effects</em>: If <code>*this</code> is valueless then
equivalent to
<code>*this = indirect(allocator_arg, alloc, std::forward&lt;U&gt;(u));</code>.
Otherwise, equivalent to
<code>**this = std::forward&lt;U&gt;(u)</code>.</p>
<p>D. <em>Returns</em>: A reference to <code>*this</code>.</p>
<h3 id="x.y-class-template-polymorphic-polymorphic">X.Y Class template
polymorphic [polymorphic]</h3>
<h4 id="x.y.1-class-template-polymorphic-synopsis-polymorphic.syn">X.Y.1
Class template polymorphic synopsis [polymorphic.syn]</h4>
<div class="sourceCode" id="cb10"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> T<span class="op">,</span> <span class="kw">class</span> Allocator <span class="op">=</span> allocator<span class="op">&lt;</span>T<span class="op">&gt;&gt;</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> polymorphic <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a>  <span class="co">// ... existing constructors</span></span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">=</span>T<span class="op">&gt;</span></span>
<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> polymorphic<span class="op">(</span>U<span class="op">&amp;&amp;</span> u<span class="op">);</span></span>
<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">=</span>T<span class="op">&gt;</span></span>
<span id="cb10-10"><a href="#cb10-10" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> polymorphic<span class="op">(</span><span class="dt">allocator_arg_t</span><span class="op">,</span> <span class="at">const</span> Allocator<span class="op">&amp;</span> a<span class="op">,</span> U<span class="op">&amp;&amp;</span> u<span class="op">);</span></span>
<span id="cb10-11"><a href="#cb10-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-12"><a href="#cb10-12" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">,</span> <span class="kw">class</span> I<span class="op">,</span> <span class="kw">class</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb10-13"><a href="#cb10-13" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> polymorphic<span class="op">(</span><span class="dt">in_place_type_t</span><span class="op">&lt;</span>U<span class="op">&gt;,</span></span>
<span id="cb10-14"><a href="#cb10-14" aria-hidden="true" tabindex="-1"></a>                                 initializer_list<span class="op">&lt;</span>I<span class="op">&gt;</span> ilist<span class="op">,</span> Us<span class="op">&amp;&amp;...</span> us<span class="op">)</span></span>
<span id="cb10-15"><a href="#cb10-15" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-16"><a href="#cb10-16" aria-hidden="true" tabindex="-1"></a>  <span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">,</span> <span class="kw">class</span> I<span class="op">,</span> <span class="kw">class</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb10-17"><a href="#cb10-17" aria-hidden="true" tabindex="-1"></a>  <span class="kw">explicit</span> <span class="kw">constexpr</span> polymorphic<span class="op">(</span><span class="dt">allocator_arg_t</span><span class="op">,</span> <span class="at">const</span> Allocator<span class="op">&amp;</span> a<span class="op">,</span></span>
<span id="cb10-18"><a href="#cb10-18" aria-hidden="true" tabindex="-1"></a>                                 <span class="dt">in_place_type_t</span><span class="op">&lt;</span>U<span class="op">&gt;,</span></span>
<span id="cb10-19"><a href="#cb10-19" aria-hidden="true" tabindex="-1"></a>                                 initializer_list<span class="op">&lt;</span>I<span class="op">&gt;</span> ilist<span class="op">,</span> Us<span class="op">&amp;&amp;...</span> us<span class="op">)</span></span>
<span id="cb10-20"><a href="#cb10-20" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-21"><a href="#cb10-21" aria-hidden="true" tabindex="-1"></a>  <span class="co">// Remaining constructors and member functions...</span></span>
<span id="cb10-22"><a href="#cb10-22" aria-hidden="true" tabindex="-1"></a><span class="op">};</span></span></code></pre></div>
<h4 id="x.z.3-constructors-polymorphic.ctor">X.Z.3 Constructors
[polymorphic.ctor]</h4>
<div class="sourceCode" id="cb11"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">=</span>T<span class="op">&gt;</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a><span class="kw">explicit</span> <span class="kw">constexpr</span> polymorphic<span class="op">(</span>U<span class="op">&amp;&amp;</span> u<span class="op">);</span></span></code></pre></div>
<p>A. <em>Constraints</em>:
<code>is_same_v&lt;remove_cv_ref_t&lt;U&gt;, U&gt;</code>.
<code>is_same_v&lt;U, polymorphic&gt;</code> is <code>false</code>.
<code>derived_from&lt;U, T&gt;</code> is <code>true</code>.
<code>is_copy_constructible_v&lt;U&gt;</code> is <code>true</code>.
<code>is_constructible_v&lt;U, U&gt;</code> is <code>true</code>.
<code>U</code> is not a specialization of <code>in_place_type_t</code>.
<code>is_default_constructible_v&lt;allocator_type&gt;</code> is
<code>true</code>.</p>
<p>B. <em>Mandates</em>: <code>T</code> is a complete type.</p>
<p>C. <em>Effects</em>: Constructs an owned object of type
<code>U</code> with <code>std​::​forward&lt;U&gt;(u)</code> using the
allocator <code>alloc</code>.</p>
<div class="sourceCode" id="cb12"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">=</span>T<span class="op">&gt;</span></span>
<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="kw">explicit</span> <span class="kw">constexpr</span> polymorphic<span class="op">(</span><span class="dt">allocator_arg_t</span><span class="op">,</span> <span class="at">const</span> Allocator<span class="op">&amp;</span> a<span class="op">,</span> U<span class="op">&amp;&amp;</span> u<span class="op">);</span></span></code></pre></div>
<p>D. <em>Constraints</em>:
<code>is_same_v&lt;remove_cv_ref_t&lt;U&gt;, U&gt;</code>.
<code>is_same_v&lt;U, polymorphic&gt;</code> is <code>false</code>.
<code>derived_from&lt;U, T&gt;</code> is <code>true</code>.
<code>is_copy_constructible_v&lt;U&gt;</code> is <code>true</code>.
<code>is_constructible_v&lt;U, U&gt;</code> is <code>true</code>.
<code>U</code> is not a specialization of <code>in_place_type_t</code>.
<code>is_default_constructible_v&lt;allocator_type&gt;</code> is
<code>true</code>.</p>
<p>E. <em>Mandates</em>: <code>T</code> is a complete type.</p>
<p>F. <em>Effects</em>: <code>alloc</code> is
direct-non-list-initialized with <code>a</code>. Constructs an owned
object of type <code>U</code> with <code>std​::​forward&lt;U&gt;(u)</code>
using the allocator <code>alloc</code>.</p>
<div class="sourceCode" id="cb13"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">,</span> <span class="kw">class</span> I<span class="op">,</span> <span class="kw">class</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="kw">explicit</span> <span class="kw">constexpr</span> polymorphic<span class="op">(</span><span class="dt">in_place_type_t</span><span class="op">&lt;</span>U<span class="op">&gt;,</span></span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a>                               initializer_list<span class="op">&lt;</span>I<span class="op">&gt;</span> ilist<span class="op">,</span> Us<span class="op">&amp;&amp;...</span> us<span class="op">)</span></span></code></pre></div>
<p>G. <em>Constraints</em>:
<code>is_same_v&lt;remove_cv_ref_t&lt;U&gt;, U&gt;</code>.
<code>is_same_v&lt;U, polymorphic&gt;</code> is <code>false</code>.
<code>derived_from&lt;U, T&gt;</code> is <code>true</code>.
<code>is_copy_constructible_v&lt;U&gt;</code> is <code>true</code>.
<code>is_constructible_v&lt;U, initializer_list&lt;I&gt;&amp;, Us...&gt;</code>
is <code>true</code>.
<code>is_default_constructible_v&lt;allocator_type&gt;</code> is
<code>true</code>.</p>
<p>H. <em>Mandates</em>: <code>T</code> is a complete type.</p>
<p>I. <em>Effects</em>: Constructs an owned object of type
<code>U</code> with the arguments <code>ilist</code>,
<code>std​::​forward&lt;Us&gt;(us)...</code> using the allocator
<code>alloc</code>.</p>
<div class="sourceCode" id="cb14"><pre
class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">template</span> <span class="op">&lt;</span><span class="kw">class</span> U<span class="op">,</span> <span class="kw">class</span> I<span class="op">,</span> <span class="kw">class</span><span class="op">...</span> Us<span class="op">&gt;</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a><span class="kw">explicit</span> <span class="kw">constexpr</span> polymorphic<span class="op">(</span><span class="dt">allocator_arg_t</span><span class="op">,</span> <span class="at">const</span> Allocator<span class="op">&amp;</span> a<span class="op">,</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a>                               <span class="dt">in_place_type_t</span><span class="op">&lt;</span>U<span class="op">&gt;,</span></span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a>                               initializer_list<span class="op">&lt;</span>I<span class="op">&gt;</span> ilist<span class="op">,</span> Us<span class="op">&amp;&amp;...</span> us<span class="op">)</span></span></code></pre></div>
<p>J. <em>Constraints</em>:
<code>is_same_v&lt;remove_cv_ref_t&lt;U&gt;, U&gt;</code>.
<code>is_same_v&lt;U, polymorphic&gt;</code> is <code>false</code>.
<code>derived_from&lt;U, T&gt;</code> is <code>true</code>.
<code>is_copy_constructible_v&lt;U&gt;</code> is <code>true</code>.
<code>is_constructible_v&lt;U, initializer_list&lt;I&gt;&amp;, Us...&gt;</code>
is <code>true</code>.</p>
<p>K. <em>Mandates</em>: <code>T</code> is a complete type.</p>
<p>L. <em>Effects</em>: <code>alloc</code> is
direct-non-list-initialized with <code>a</code>. Constructs an owned
object of type <code>U</code> with the arguments <code>ilist</code>,
<code>std​::​forward&lt;Us&gt;(us)...</code> using the allocator
<code>alloc</code>.</p>
<h2 id="reference-implementation">Reference implementation</h2>
<p>A C++20 (and C++14 compatible) reference implementation of the work
discussed in this proposal is available on GitHub at
[https://www.github.com/jbcoe/value_types].</p>
<h2 id="acknowledgements">Acknowledgements</h2>
<p>Many thanks to Neelofer Banglawala for collating information and
preparing this draft at extremely short notice.</p>
<h2 id="references">References</h2>
<p>[1] <em><code>indirect</code> and <code>polymorphic</code>:
Vocabulary Types for Composite Class Design</em>,<br />
J. B. Coe, A. Peacock, and S. Parent, 2024<br />
<a
href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3019r6.html"
class="uri">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p3019r6.html</a></p>
<p>[2] <em>An allocator-aware optional type</em>,<br />
P. Halpern, N. D. Ranns, V. Voutilainen, 2024<br />
<a
href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2047r7.html"
class="uri">https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2047r7.html</a></p>
