<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta charset="utf-8">
<title>C++ Standard Library Immediate Issues to be moved in Issaquah, Feb. 2023</title>
<style type="text/css">
  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;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table {border-collapse: collapse;}
</style>
</head>
<body>
<h1>C++ Standard Library Immediate Issues to be moved in Issaquah, Feb. 2023</h1>
<table>
<tr>
<td align="left">Doc. no.</td>
<td align="left">P2790R0</td>
</tr>
<tr>
<td align="left">Date:</td>
<td align="left"><p>2023-02-10</p>
</td>
</tr>
<tr>
<td align="left">Audience:</td>
<td align="left">WG21</td>
</tr>
<tr>
<td align="left">Reply to:</td>
<td align="left">Jonathan Wakely &lt;<a href="mailto:lwgchair@gmail.com">lwgchair@gmail.com</a>&gt;</td>
</tr>
</table>
<h2 id="immediate">Immediate Issues</h2>
<hr>
<h3><a name="3441" href="https://cplusplus.github.io/LWG/lwg-active.html#3441">3441</a>. Misleading note about calls to customization points</h3>
<p><b>Section:</b> 16.4.5.2.1 <a href="https://wg21.link/namespace.std">[namespace.std]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Michael Park <b>Opened:</b> 2020-05-08 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>1
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#namespace.std">active issues</a> in [namespace.std].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#namespace.std">issues</a> in [namespace.std].</p>
<p><b>Discussion:</b></p>
<p>
<a href="https://wg21.link/p0551">P0551</a> (Thou Shalt Not Specialize <tt>std</tt> Function Templates!) 
added a clause in [namespace.std]/7:
</p>
<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;">
<p>
Other than in namespace <tt>std</tt> or in a namespace within namespace <tt>std</tt>, a program may provide 
an overload for any library function template designated as a customization point, provided that 
(a) the overload's declaration depends on at least one user-defined type and (b) the overload meets 
the standard library requirements for the customization point. (footnote 174) [<i>Note:</i> This permits a (qualified 
or unqualified) call to the customization point to invoke the most appropriate overload for 
the given arguments. &mdash; <i>end note</i>]
</p>
</blockquote>
<p>
Given that <tt>std::swap</tt> is a designated customization point, the note seems to suggest the following:
</p>
<blockquote><pre>
namespace N {
  struct X {};
  void swap(X&amp;, X&amp;) {}
}

N::X a, b;
std::swap(a, b); // <span style="color:#C80000;font-weight:bold">qualified call to customization point finds N::swap?</span>
</pre></blockquote>
<p>
This is not what happens, as the call to <tt>std::swap</tt> does not find <tt>N::swap</tt>.
</p>

<p><i>[2020-07-17; Priority set to 1 in telecon]</i></p>

<p>Related to <a href="https://cplusplus.github.io/LWG/lwg-active.html#3442">3442</a>.</p>

<p><i>[2020-09-11; discussed during telecon]</i></p>

<p>The note is simply bogus, not backed up by anything normative.
The normative part of the paragraph is an unacceptable landgrab on those
identifiers.
We have no right telling users they can't use the names <tt>data</tt>
and <tt>size</tt> unless they do exactly what we say <tt>std::data</tt>
and <tt>std::size</tt> do.
The library only ever uses <tt>swap</tt> unqualified, so the effect of
declaring the others as designated customization points is unclear.
</p>
<p>
The rule only needs to apply to such overloads <em>when actually found
by overload resolution</em> in a context that expects the semantics of
the customization point.
</p>
<p>
Frank: do we need to designate <tt>operator&lt;&lt;</tt> as a
customization point?  Users overload that in their own namespaces all the time.
</p>
<p>
Walter: This clearly needs a paper.
</p>

<p><i>[2020-10-02; status to Open]</i></p>


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

<ol>
<li><p>Modify 16.4.5.2.1 <a href="https://wg21.link/namespace.std">[namespace.std]</a> as indicated:</p>

<blockquote>
<p>
-7- Other than in namespace <tt>std</tt> or in a namespace within namespace <tt>std</tt>, a program 
may provide an overload for any library function template designated as a customization point, 
provided that (a) the overload's declaration depends on at least one user-defined type and (b) the 
overload meets the standard library requirements for the customization point. (footnote 173) 
<del>[<i>Note:</i> This permits a (qualified or unqualified) call to the customization point
to invoke the most appropriate overload for the given arguments. &mdash; <i>end note</i>]</del>
</p>
</blockquote>
</li>

</ol>
</blockquote>

<p><i>[Issaquah 2023-02-09; Jonathan provides improved wording]</i></p>

<p>The normative part of 16.4.5.2.1 <a href="https://wg21.link/namespace.std">[namespace.std]</a> paragraph 7
(i.e. not the note and the footnote) does not actually do anything
except tell users they're not allowed to use the names
<tt>begin</tt>, <tt>size</tt> etc. unless they conform to the
provisions of paragraph 7. This means a program that contains the
following declaration might have undefined behaviour:
<pre><code>namespace user { int data(int, int); }</code></pre>
This is not OK! It's not even clear what "the requirements for
the customization point" are, if users wanted to meet them.
It's not even clear what "provide an overload" means.
</p>
<p>In particular, paragraph 7 does not give permission for the
designated customization points to actually <i>use</i> such
overloads. Just by forbidding users from using <tt>data</tt>
for their own functions isn't sufficient to allow the library to
use ADL to call <tt>data</tt>, and it's unclear why we'd want
that anyway (what problem with <tt>std::data</tt> are we trying
to solve that way?). As shown in LWG <a href="https://cplusplus.github.io/LWG/lwg-active.html#3442">3442</a>, if
<tt>std::data</tt> became a customization point that would be
a backwards-incompatible change, and create a portability problem
if some implementations did that and others didn't.
</p>
<p>So the non-normative note and footnote make claims that do not
follow from the normative wording, and should be removed.</p>

<p>The only one of the designated customization points that
is actually looked up using ADL is <tt>std::swap</tt>, but how that
works is fully specified by 16.4.2.2 <a href="https://wg21.link/contents">[contents]</a> and
16.4.4.3 <a href="https://wg21.link/swappable.requirements">[swappable.requirements]</a>. The additional specification
that it's a designated customization point serves no benefit.
In particular, the permission that the note and footnote claim
exists is not needed. We specify precisely how <tt>swap</tt>
calls are performed.
We don't even need to say that user overloads of <tt>swap</tt>
in their own namespaces must meet the library requirements,
because the "swappable with" and <i>Cpp17Swappable</i> requirements
state the required semantics, and functions that use <tt>swap</tt>
have preconditions that the types are swappable. So we correctly
impose preconditions <b>in the places that actually call swap</b>,
and don't need to globally make it undefined for any function
called <tt>swap</tt> to not meet the requirements, even if that
function is never found by ADL by the library (e.g. because it's
in a namespace that is never an associated namespace of any types
used with library components that require swappable types).
</p>
<p>Paragraph 7 and its accompanying notes should go.</p>

<p><i>[Issaquah 2023-02-09; LWG]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>
<li><p>Modify 16.4.5.2.1 <a href="https://wg21.link/namespace.std">[namespace.std]</a> as indicated:</p>

<blockquote class="note">[<i>Drafting note</i>:
This should also remove the only index entry for "customization point".
]</blockquote>

<blockquote>
<p><del>-7-
Other than in namespace <tt>std</tt> or in a namespace within namespace <tt>std</tt>,
a program may provide an overload for any library function template designated as a
<i>customization point</i>, provided that
(a) the overload's declaration depends on at least one user-defined type and
(b) the overload meets the standard library requirements for the customization point.
<sup>163</sup>
</del>
</p>
<p>
<del>
[<i>Note 3</i>:
This permits a (qualified or unqualified) call to the customization point
to invoke the most appropriate overload for the given arguments.
&mdash; <i>end note</i>]
</del>
</p>
<p>
<del>
163)
Any library customization point must be prepared to work adequately with
any user-defined overload that meets the minimum requirements of this document.
Therefore an implementation can elect, under the as-if rule
(6.9.1 <a href="https://wg21.link/intro.execution">[intro.execution]</a>), to provide any customization point
in the form of an instantiated function object (22.10 <a href="https://wg21.link/function.objects">[function.objects]</a>)
even though the customization point's specification is in the form of a function template.
The template parameters of each such function object and the function parameters
and return type of the object's <tt>operator()</tt> must match those of the
corresponding customization point's specification.
</del>
</p>
</blockquote>
</li>

<li><p>Modify 22.2.2 <a href="https://wg21.link/utility.swap">[utility.swap]</a> as indicated:</p>

<blockquote>
<pre><code>
template&lt;class T&gt;
  constexpr void swap(T&amp; a, T&amp; b) noexcept(<i>see below</i>);
</code></pre>
<p>-1- <i>Constraints</i>:
<tt>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>.
</p>
<p>-2- <i>Preconditions</i>:
Type <tt>T</tt> meets the <i>Cpp17MoveConstructible</i> (Table 32)
and <i>Cpp17MoveAssignable</i> (Table 34) requirements.
</p>
<p>-3- <i>Effects</i>:
Exchanges values stored in two locations.
</p>
<p>-4- <i>Remarks</i>:
<del>
This function is a designated customization point
(16.4.5.2.1 <a href="https://wg21.link/namespace.std">[namespace.std]</a>).
</del>
The exception specification is equivalent to:
<pre><code>
is_nothrow_move_constructible_v&lt;T&gt; &amp;&amp; is_nothrow_move_assignable_v&lt;T&gt;
</code></pre>
</p>
</blockquote>
</li>

<li><p>Modify 25.7 <a href="https://wg21.link/iterator.range">[iterator.range]</a> as indicated:</p>

<blockquote>
<p>-1-
In addition to being available via inclusion of the &lt;iterator&gt; header,
the function templates in 25.7 <a href="https://wg21.link/iterator.range">[iterator.range]</a> are available when
any of the following headers are included:
&lt;array&gt; (24.3.2 <a href="https://wg21.link/array.syn">[array.syn]</a>),
&lt;deque&gt; (24.3.3 <a href="https://wg21.link/deque.syn">[deque.syn]</a>),
&lt;forward_list&gt; (24.3.4 <a href="https://wg21.link/forward.list.syn">[forward.list.syn]</a>),
&lt;list&gt; (24.3.5 <a href="https://wg21.link/list.syn">[list.syn]</a>),
&lt;map&gt; (24.4.2 <a href="https://wg21.link/associative.map.syn">[associative.map.syn]</a>),
&lt;regex&gt; (32.3 <a href="https://wg21.link/re.syn">[re.syn]</a>),
&lt;set&gt; (24.4.3 <a href="https://wg21.link/associative.set.syn">[associative.set.syn]</a>),
&lt;span&gt; (24.7.2.1 <a href="https://wg21.link/span.syn">[span.syn]</a>),
&lt;string&gt; (23.4.2 <a href="https://wg21.link/string.syn">[string.syn]</a>),
&lt;string_view&gt; ( [string.view.syn]),
&lt;unordered_map&gt; (24.5.2 <a href="https://wg21.link/unord.map.syn">[unord.map.syn]</a>),
&lt;unordered_set&gt; (24.5.3 <a href="https://wg21.link/unord.set.syn">[unord.set.syn]</a>),
and &lt;vector&gt; (24.3.6 <a href="https://wg21.link/vector.syn">[vector.syn]</a>).
<del>
Each of these templates is a designated customization point
(16.4.5.2.1 <a href="https://wg21.link/namespace.std">[namespace.std]</a>).
</del>
</p>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3622" href="https://cplusplus.github.io/LWG/lwg-active.html#3622">3622</a>. Misspecified transitivity of equivalence in &sect;[unord.req.general]</h3>
<p><b>Section:</b> 24.2.8.1 <a href="https://wg21.link/unord.req.general">[unord.req.general]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Thomas K&ouml;ppe <b>Opened:</b> 2021-10-20 <b>Last modified:</b> 2023-02-09</p>
<p><b>Priority: </b>2
</p>
<p><b>Discussion:</b></p>
<p>
The paper <a href="https://wg21.link/P2077R3">P2077R3</a> ("Heterogeneous erasure overloads for associative containers") 
adds a new variable <tt>kx</tt> with specific meaning for use in the Table of Unordered Associative 
Container Requirements, 24.2.8.1 <a href="https://wg21.link/unord.req.general">[unord.req.general]</a> p11, which is meant to stand for an 
equivalence class of heterogeneous values that can be compared with container keys.
<p/>
One property required of <tt>kx</tt> is transitivity of equality/equivalence, but this is currently specified as:
</p>
<blockquote><p>
"<tt>kx</tt> is a value such that [&hellip;] <tt>(eq(r1, kx) &amp;&amp; eq(r1, r2)) == eq(r2, kx)</tt> [&hellip;], 
where <tt>r1</tt> and <tt>r2</tt> are [any] keys".
</p></blockquote>
<p>
But this doesn't seem right. Transitivity means that <tt>eq(r1, kx) &amp;&amp; eq(r1, r2)</tt> being 
true implies <tt>eq(r2, kx)</tt> being true, but it does <em>not</em> imply that both sides are equal 
in general. In particular, <tt>eq(r2, kx)</tt> can be true even when <tt>eq(r1, kx) &amp;&amp; eq(r1, r2)</tt> 
is false.
<p/>
More abstractly, equality is transitive, but inequality is not.
<p/>
The new wording appears to have been copied from the pre-existing wording for the variable "<tt>ke</tt>", which 
suffers from the same problem, and so we propose to fix both cases.
</p>

<p><i>[2022-01-29; Reflector poll]</i></p>

<p>
Set priority to 2 after reflector poll.
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">


<p>
This wording is relative to <a href="https://wg21.link/n4901">N4901</a>.
</p>

<ol>
<li><p>Modify 24.2.8.1 <a href="https://wg21.link/unord.req.general">[unord.req.general]</a> as indicated:</p>

<blockquote>
<ol style="list-style-type: none">
<li><p>[&hellip;]</p></li>
<li><p>(11.19) &mdash; <tt>ke</tt> is a value such that</p>
<ol style="list-style-type: none">
<li><p>(11.19.1) &mdash; <tt>eq(r1, ke) == eq(ke, r1)</tt>,</p></li>
<li><p>(11.19.2) &mdash; <tt>hf(r1) == hf(ke)</tt> if <tt>eq(r1, ke)</tt> is <tt>true</tt>, and</p></li>
<li><p>(11.19.3) &mdash; <del><tt>(eq(r1, ke) &amp;&amp; eq(r1, r2)) == eq(r2, ke)</tt></del><ins><tt>eq(ke, r2)</tt> 
is <tt>true</tt> if <tt>eq(ke, r1) &amp;&amp; eq(r1, r2)</tt> is <tt>true</tt></ins>,</p></li>
</ol>
<p>where <tt>r1</tt> and <tt>r2</tt> are keys of elements in <tt>a_tran</tt>,</p>
</li>
<li><p>(11.20) &mdash; <tt>kx</tt> is a value such that</p>
<ol style="list-style-type: none">
<li><p>(11.20.1) &mdash; <tt>eq(r1, kx) == eq(kx, r1)</tt>,</p></li>
<li><p>(11.20.2) &mdash; <tt>hf(r1) == hf(kx)</tt> if <tt>eq(r1, kx)</tt> is <tt>true</tt>,</p></li>
<li><p>(11.20.3) &mdash; <del><tt>(eq(r1, kx) &amp;&amp; eq(r1, r2)) == eq(r2, kx)</tt></del><ins><tt>eq(kx, r2)</tt> 
is <tt>true</tt> if <tt>eq(kx, r1) &amp;&amp; eq(r1, r2)</tt> is <tt>true</tt></ins>, and</p></li>
<li><p>(11.20.4) &mdash; <tt>kx</tt> is not convertible to either <tt>iterator</tt> or <tt>const_iterator</tt>,</p></li>
</ol>
<p>where <tt>r1</tt> and <tt>r2</tt> are keys of elements in <tt>a_tran</tt>,</p>
</li>
<li><p>[&hellip;]</p></li>
</ol>
</blockquote>
</li>
</ol>
</blockquote>


<p><i>[2022-02-07 Tim comments and provides updated wording]</i></p>

<p>
For heterogeneous lookup on unordered containers to work properly, we
need all keys comparing equal to the transparent key to be grouped
together. Since the only keys guaranteed to be so grouped are the ones
that are equal according to <tt>eq</tt>, we cannot allow 
<tt>eq(r1, r2) == false</tt> but <tt>eq(r1, ke) == true &amp;&amp;
eq(r2, ke) == true</tt>. The one-way
transitivity of equality is insufficient.
<p/>
We need both of the following:
</p>
<ul>
<li>
if <tt>eq(r1, ke)</tt> is <tt>true</tt> and <tt>eq(r1, r2)</tt> is <tt>true</tt> 
then <tt>eq(r2, ke)</tt> is <tt>true</tt>.
</li>
<li>
if <tt>eq(r1, ke)</tt> is <tt>true</tt> and <tt>eq(r2, ke)</tt> is <tt>true</tt> 
then <tt>eq(r1, r2)</tt> is <tt>true</tt>
</li>
</ul>

<p>
In a table:
</p>

<table border="1">
    <thead>
        <tr>
            <th>eq(r1, ke)</th>
            <th>eq(r1, r2)</th>
            <th>eq(r2, ke)</th>
            <th>OK?</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>T</td>
            <td>T</td>
            <td>T</td>
            <td>Y</td>
        </tr>
        <tr>
            <td>T</td>
            <td>T</td>
            <td>F</td>
            <td>N</td>
        </tr>
        <tr>
            <td>T</td>
            <td>F</td>
            <td>T</td>
            <td>N</td>
        </tr>
        <tr>
            <td>T</td>
            <td>F</td>
            <td>F</td>
            <td>Y</td>
        </tr>
        <tr>
            <td>F</td>
            <td>T</td>
            <td>T</td>
            <td>N</td>
        </tr>
        <tr>
            <td>F</td>
            <td>T</td>
            <td>F</td>
            <td>Y</td>
        </tr>
        <tr>
            <td>F</td>
            <td>F</td>
            <td>T</td>
            <td>Y</td>
        </tr>
        <tr>
            <td>F</td>
            <td>F</td>
            <td>F</td>
            <td>Y</td>
        </tr>
    </tbody>
</table>

<p><i>[Issaquah 2023-02-08; LWG]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>
<li><p>Modify 24.2.8.1 <a href="https://wg21.link/unord.req.general">[unord.req.general]</a> as indicated:</p>

<blockquote>
<ol style="list-style-type: none">
<li><p>[&hellip;]</p></li>
<li><p>(10.20) &mdash; <tt>ke</tt> is a value such that</p>
<ol style="list-style-type: none">
<li><p>(10.20.1) &mdash; <tt>eq(r1, ke) == eq(ke, r1)</tt>,</p></li>
<li><p>(10.20.2) &mdash; <tt>hf(r1) == hf(ke)</tt> if <tt>eq(r1, ke)</tt> is <tt>true</tt>, and</p></li>
<li><p>(10.20.3) &mdash; <del><tt>(eq(r1, ke) &amp;&amp; eq(r1, r2)) == eq(r2, ke)</tt></del><ins>if any two of
<tt>eq(r1, ke)</tt>, <tt>eq(r2, ke)</tt> and <tt>eq(r1, r2)</tt> are <tt>true</tt>, then all three are <tt>true</tt></ins>,</p></li>
</ol>
<p>where <tt>r1</tt> and <tt>r2</tt> are keys of elements in <tt>a_tran</tt>,</p>
</li>
<li><p>(10.21) &mdash; <tt>kx</tt> is a value such that</p>
<ol style="list-style-type: none">
<li><p>(10.21.1) &mdash; <tt>eq(r1, kx) == eq(kx, r1)</tt>,</p></li>
<li><p>(10.21.2) &mdash; <tt>hf(r1) == hf(kx)</tt> if <tt>eq(r1, kx)</tt> is <tt>true</tt>,</p></li>
<li><p>(10.21.3) &mdash; <del><tt>(eq(r1, kx) &amp;&amp; eq(r1, r2)) == eq(r2, kx)</tt></del><ins>if any two of
<tt>eq(r1, kx)</tt>, <tt>eq(r2, kx)</tt> and <tt>eq(r1, r2)</tt> are <tt>true</tt>, then all three are <tt>true</tt></ins>, and</p></li>
<li><p>(10.21.4) &mdash; <tt>kx</tt> is not convertible to either <tt>iterator</tt> or <tt>const_iterator</tt>,</p></li>
</ol>
<p>where <tt>r1</tt> and <tt>r2</tt> are keys of elements in <tt>a_tran</tt>,</p>
</li>
<li><p>[&hellip;]</p></li>
</ol>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3631" href="https://cplusplus.github.io/LWG/lwg-active.html#3631">3631</a>. <tt>basic_format_arg(T&amp;&amp;)</tt> should use <tt>remove_cvref_t&lt;T&gt;</tt> throughout</h3>
<p><b>Section:</b> 22.14.8.1 <a href="https://wg21.link/format.arg">[format.arg]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Tim Song <b>Opened:</b> 2021-11-03 <b>Last modified:</b> 2023-02-09</p>
<p><b>Priority: </b>3
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#format.arg">active issues</a> in [format.arg].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#format.arg">issues</a> in [format.arg].</p>
<p><b>Discussion:</b></p>
<p>
<a href="https://wg21.link/P2418R2">P2418R2</a> changed <tt>basic_format_arg</tt>'s constructor to take a forwarding
reference but didn't change 22.14.8.1 <a href="https://wg21.link/format.arg">[format.arg]</a>/5 which inspects various
properties of <tt>T</tt>. Now that the deduced type can be <i>cvref</i>-qualified,
they need to be removed before the checks.
</p>

<p><i>[2022-01-29; Reflector poll]</i></p>

<p>
Set priority to 3 after reflector poll.
</p>
<p>
Two suggestions to just change it to be <tt>T&amp;</tt> because we don't
need forwarding references here, and only accepting lvalues prevents
forming dangling references.
</p>

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

<ol>
<li><p>Modify 22.14.8.1 <a href="https://wg21.link/format.arg">[format.arg]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class T&gt; explicit basic_format_arg(T&amp;&amp; v) noexcept;
</pre>
<blockquote>
<p>
<ins>-?- Let <tt>TD</tt> be <tt>remove_cvref_t&lt;T&gt;</tt>.</ins>
<p/>
-4- <i>Constraints:</i> The template specialization
</p>
<blockquote><pre>
typename Context::template formatter_type&lt;<del>remove_cvref_t&lt;T&gt;</del><ins>TD</ins>&gt;
</pre></blockquote>
<p>
meets the <i>BasicFormatter</i> requirements (22.14.6.1 <a href="https://wg21.link/formatter.requirements">[formatter.requirements]</a>). The extent to
which an implementation determines that the specialization meets the <i>BasicFormatter</i>
requirements is unspecified, except that as a minimum the expression
</p>
<blockquote><pre>
typename Context::template formatter_type&lt;<del>remove_cvref_t&lt;T&gt;</del><ins>TD</ins>&gt;()
  .format(declval&lt;T&amp;&gt;(), declval&lt;Context&amp;&gt;())
</pre></blockquote>
<p>
shall be well-formed when treated as an unevaluated operand (7.2.3 <a href="https://wg21.link/expr.context">[expr.context]</a>).
<p/>
-5- <i>Effects:</i>
</p>
<ol style="list-style-type:none">
<li><p>(5.1) &mdash; if <tt>T<ins>D</ins></tt> is <tt>bool</tt> or <tt>char_type</tt>, initializes <tt>value</tt> with <tt>v</tt>;</p></li>
<li><p>(5.2) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is <tt>char</tt> and <tt>char_type</tt> is <tt>wchar_t</tt>,
initializes <tt>value</tt> with <tt>static_cast&lt;wchar_t&gt;(v)</tt>;</p></li>
<li><p>(5.3) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is a signed integer type (6.8.2 <a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a>) and
<tt>sizeof(T<ins>D</ins>) &lt;= sizeof(int)</tt>, initializes <tt>value</tt> with <tt>static_cast&lt;int&gt;(v)</tt>;</p></li>
<li><p>(5.4) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is an unsigned integer type and <tt>sizeof(T<ins>D</ins>) &lt;= sizeof(unsigned int)</tt>,
initializes <tt>value</tt> with <tt>static_cast&lt;unsigned int&gt;(v)</tt>;</p></li>
<li><p>(5.5) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is a signed integer type and <tt>sizeof(T<ins>D</ins>) &lt;= sizeof(long long int)</tt>,
initializes <tt>value</tt> with <tt>static_cast&lt;long long int&gt;(v)</tt>;</p></li>
<li><p>(5.6) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is an unsigned integer type and <tt>sizeof(T<ins>D</ins>) &lt;= sizeof(unsigned long long int)</tt>, initializes <tt>value</tt> with <tt>static_cast&lt;unsigned long long int&gt;(v)</tt>;</p></li>
<li><p>(5.7) &mdash; otherwise, initializes <tt>value</tt> with <tt>handle(v)</tt>.</p></li>
</ol>
</blockquote>
</blockquote>
</li>

</ol>
</blockquote>

<p><i>[2022-10-19; Jonathan provides improved wording]</i></p>

<p>
During reflector prioritization it was pointed out that forwarding references
are unnecessary (arguments are always lvalues), and so using <tt>T&amp;</tt>
would be simpler.
</p>
<p>
In order to resolve the overload ambiguities discussed in <a href="https://cplusplus.github.io/LWG/lwg-active.html#3718">3718</a>
replace all unary constructor overloads with a single constructor that works
for any formattable type.
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">

<p>
This wording is relative to <a href="https://wg21.link/N4917">N4917</a>.
</p>

<ol>
<li><p>Modify 22.14.8.1 <a href="https://wg21.link/format.arg">[format.arg]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class T&gt; explicit basic_format_arg(T&amp;<del>&amp;</del> v) noexcept;
</pre>
<blockquote>
<p>
-4- <i>Constraints:</i>
<ins><tt>T</tt> satisfies <tt>formattable&lt;char_type&gt;</tt>.</ins>
<del>The template specialization</del>
</p>
<blockquote><pre><del>
typename Context::template formatter_type&lt;remove_cvref_t&lt;T&gt;&gt;
</del></pre></blockquote>
<p><del>
meets the <i>BasicFormatter</i> requirements (22.14.6.1 <a href="https://wg21.link/formatter.requirements">[formatter.requirements]</a>). The extent to
which an implementation determines that the specialization meets the <i>BasicFormatter</i>
requirements is unspecified, except that as a minimum the expression
</del></p>
<blockquote><pre><del>
typename Context::template formatter_type&lt;remove_cvref_t&lt;T&gt;&gt;()
  .format(declval&lt;T&amp;&gt;(), declval&lt;Context&amp;&gt;())
</del></pre></blockquote>
<p><del>
shall be well-formed when treated as an unevaluated operand (7.2.3 <a href="https://wg21.link/expr.context">[expr.context]</a>).
</del></p>
<p><ins>-?- <i>Preconditions</i>:
If <tt>decay_t&lt;T&gt;</tt> is <tt>char_type*</tt> or <tt>const char_type*</tt>,
<tt>static_cast&lt;const char_type*&gt;(v)</tt> points to a NTCTS
(3.36 <a href="https://wg21.link/defns.ntcts">[defns.ntcts]</a>).</ins>
</p>
<p>
-5- <i>Effects:</i>
<ins>Let <tt>TD</tt> be <tt>remove_const_t&lt;T&gt;</tt>.</ins>
</p>
<ol style="list-style-type:none">
<li><p>(5.1) &mdash; if <tt>T<ins>D</ins></tt> is <tt>bool</tt> or <tt>char_type</tt>, initializes <tt>value</tt> with <tt>v</tt>;</p></li>
<li><p>(5.2) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is <tt>char</tt> and <tt>char_type</tt> is <tt>wchar_t</tt>,
initializes <tt>value</tt> with <tt>static_cast&lt;wchar_t&gt;(v)</tt>;</p></li>
<li><p>(5.3) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is a signed integer type (6.8.2 <a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a>) and
<tt>sizeof(T<ins>D</ins>) &lt;= sizeof(int)</tt>, initializes <tt>value</tt> with <tt>static_cast&lt;int&gt;(v)</tt>;</p></li>
<li><p>(5.4) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is an unsigned integer type and <tt>sizeof(T<ins>D</ins>) &lt;= sizeof(unsigned int)</tt>,
initializes <tt>value</tt> with <tt>static_cast&lt;unsigned int&gt;(v)</tt>;</p></li>
<li><p>(5.5) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is a signed integer type and <tt>sizeof(T<ins>D</ins>) &lt;= sizeof(long long int)</tt>,
initializes <tt>value</tt> with <tt>static_cast&lt;long long int&gt;(v)</tt>;</p></li>
<li><p>(5.6) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is an unsigned integer type and <tt>sizeof(T<ins>D</ins>) &lt;= sizeof(unsigned long long int)</tt>, initializes <tt>value</tt> with <tt>static_cast&lt;unsigned long long int&gt;(v)</tt>;</p></li>

<li><p><ins>(5.?) &mdash; otherwise, if <tt>TD</tt> is a standard floating-point type, initializes <tt>value</tt> with <tt>v</tt>;</ins></p></li>

<li><p><ins>(5.?) &mdash; otherwise, if <tt>TD</tt> is a specialization of
<tt>basic_string_view</tt> or <tt>basic_string</tt> and <tt>TD::value_type</tt> is <tt>char_type</tt>, initializes <tt>value</tt> with <tt>basic_string_view&lt;char_type&gt;(v.data(), v.size())</tt>;</ins></p></li>

<li><p><ins>(5.?) &mdash; otherwise, if <tt>decay_t&lt;TD&gt;</tt> is <tt>char_type*</tt> or <tt>const char_type*</tt>, initializes <tt>value</tt> with <tt>static_cast&lt;const char_type*&gt;(v)</tt>;</ins></p></li>

<li><p><ins>(5.?) &mdash; otherwise, if <tt>is_void_v&lt;remove_pointer_t&lt;TD&gt;&gt;</tt> is <tt>true</tt> or <tt>is_null_pointer_v&lt;TD&gt;</tt> is <tt>true</tt>, initializes <tt>value</tt> with <tt>static_cast&lt;const void*&gt;(v)</tt>;</ins></p></li>

<li><p>(5.7) &mdash; otherwise, initializes <tt>value</tt> with <tt>handle(v)</tt>.</p></li>
</ol>
<p><ins>-?- [<i>Note</i>: Constructing <tt>basic_format_arg</tt> from a pointer
to a member is ill-formed unless the user provides an enabled specialization
of <tt>formatter</tt> for that pointer to member type. &mdash; <i>end note</i>]
</ins></p>
</blockquote>

<pre><del>
explicit basic_format_arg(float n) noexcept;
explicit basic_format_arg(double n) noexcept;
explicit basic_format_arg(long double n) noexcept;
</del></pre>
<blockquote>
<p><del>-6- <i>Effects</i>: Initializes <tt>value</tt> with <tt>n</tt>.</del></p>
</blockquote>

<pre><del>
explicit basic_format_arg(const char_type* s) noexcept;
</del></pre>
<blockquote>
<p><del>-7- <i>Preconditions</i>: <tt>s</tt> points to a NTCTS (3.36 <a href="https://wg21.link/defns.ntcts">[defns.ntcts]</a>).</del></p>
<p><del>-8- <i>Effects</i>: Initializes <tt>value</tt> with <tt>s</tt>.</del></p>
</blockquote>

<pre><del>
template&lt;class traits&gt;>
  explicit basic_format_arg(basic_string_view&lt;char_type, traits&gt; s) noexcept;
</del></pre>
<blockquote>
<p><del>-9- <i>Effects</i>: Initializes <tt>value</tt> with <tt>basic_string_view&lt;char_type&gt;(s.data(), s.size())</tt>.</del></p>
</blockquote>

<pre><del>
template&lt;class traits, class Allocator&gt;>
  explicit basic_format_arg(
    const basic_string&lt;char_type, traits, Allocator&gt;&amp; s) noexcept;
</del></pre>
<blockquote>
<p><del>-10- <i>Effects</i>: Initializes <tt>value</tt> with <tt>basic_string_view&lt;char_type&gt;(s.data(), s.size())</tt>.</del></p>
</blockquote>

<pre><del>
explicit basic_format_arg(nullptr_t) noexcept;
</del></pre>
<blockquote>
<p><del>-11- <i>Effects</i>: Initializes <tt>value</tt> with <tt>static_cast&lt;const void*&gt;(nullptr)</tt>.</del></p>
</blockquote>

<pre><del>
template&lt;class T&gt; explicit basic_format_arg(T* p) noexcept;
</del></pre>
<blockquote>
<p><del>-12- <i>Constraints</i>: <tt>is_void_v&lt;T&gt;</tt> is <tt>true</tt>.</del></p>
<p><del>-13- <i>Effects</i>: Initializes <tt>value</tt> with <tt>p</tt>.</del></p>
<p><del>-14- <i>[Note</i>: Constructing <tt>basic_format_arg</tt> from a pointer
to a member is ill-formed unless the user provides an enabled specialization
of <tt>formatter</tt> for that pointer to member type. &mdash; <i>end note]</i>
</del></p>
</blockquote>

</blockquote>
</li>

<li><p>Modify 22.14.8.1 <a href="https://wg21.link/format.arg">[format.arg]</a> p17 and p18 as indicated:</p>

<blockquote>
<pre>
template&lt;class T&gt; explicit handle(T&amp;<del>&amp;</del> v) noexcept;
</pre>
<blockquote>
<p>-17- Let</p>
<ol style="list-style-type:none">
<li><p>&mdash; (17.1)
<tt>TD</tt> be <tt>remove_<del>cvref</del><ins>const</ins>_t&lt;T&gt;</tt>,
</p></li>
<li><p><del>&mdash; (17.2)
<tt><i>const-formattable</i></tt> be <tt>true</tt> if
<tt>typename Context::template formatter_type&lt;TD&gt;().format(declval&lt;const TD&amp;&gt;(), declval&lt;Context&amp;&gt;())</tt>
is well-formed, otherwise <tt>false</tt>,</del>
</p></li>
<li><p>&mdash; (17.3)
<tt>TQ</tt> be <tt>const TD</tt> if
<del><tt><i>const-formattable</i></tt> is <tt>true</tt></del>
<ins><tt>const TD</tt> satisfies <tt>formattable&lt;char_type&gt;</tt></ins>
and <tt>TD</tt> otherwise.
</p></li>
</ol>
<p>-18- <i>Mandates</i>:
<tt><del><i>const-formattable</i></del>
<ins><tt>formattable&lt;const TD, char_type&gt;</tt></ins>
||
!is_const_v&lt;<del>remove_reference_t&lt;</del>T<del>&gt;</del></tt>
is <tt>true</tt>.
</p>
<p>-19- <i>Effects</i>:
Initializes <tt>ptr_</tt> with <tt>addressof(val)</tt> and <tt>format_</tt> with
<blockquote><pre>
[](basic_format_parse_context&lt;char_type&gt;&amp; parse_ctx,
   Context&amp; format_ctx, const void* ptr) {
  typename Context::template formatter_type&lt;TD&gt; f;
  parse_ctx.advance_to(f.parse(parse_ctx));
  format_ctx.advance_to(f.format(*const_cast&lt;TQ*&gt;(static_cast&lt;const TD*&gt;(ptr)),
                                 format_ctx));
}
</pre></blockquote>
</p>
</blockquote>
</blockquote>
</li>
</ol>

</blockquote>

<p><i>[2022-11-10; Jonathan provides improved wording]</i></p>


<p><i>[2022-11-29; Casey expands the issue to also cover <tt>make_format_args</tt>]</i></p>


<p><i>[2023-01-11; Jonathan adds the missing edits to the class synopsis]</i></p>


<p><i>[Issaquah 2023-02-07; LWG]</i></p>

<p>
Edited proposed resolution to
remove extra <ins><tt>=</tt></ins> in concept definition
and capitialize start of (5.1).
Move to Immediate for C++23
</p>



<p id="res-3631"><b>Proposed resolution:</b></p>

<p>
This wording is relative to <a href="https://wg21.link/N4917">N4917</a>.
</p>

<ol>
<li><p>Modify 22.14.6.2 <a href="https://wg21.link/format.formattable">[format.formattable]</a> as indicated:</p>

<p>
-1- Let <tt><i>fmt-iter-for</i>&lt;charT&gt;</tt> be an unspecified type that models
<tt>output_iterator&lt;const charT&amp;&gt;</tt> (25.3.4.10 <a href="https://wg21.link/iterator.concept.output">[iterator.concept.output]</a>).
</p>

<blockquote><pre><ins>
  template&lt;class T, class Context,
           class Formatter = typename Context::template formatter_type&lt;remove_const_t&lt;T&gt;&gt;&gt;
    concept <i>formattable-with</i> =         <i>// exposition only</i>
      semiregular&lt;Formatter&gt; &amp;&amp;
        requires (Formatter&amp; f, const Formatter&amp; cf, T&amp;&amp; t, Context fc,
                 basic_format_parse_context&lt;typename Context::char_type&gt; pc)
       {
         { f.parse(pc) } -&gt; same_as&lt;typename decltype(pc)::iterator&gt;;
         { cf.format(t, fc) } -&gt; same_as&lt;typename Context::iterator&gt;;
       };</ins>

template&lt;class T, class charT&gt;
  concept formattable =
<del>    semiregular&lt;formatter&lt;remove_cvref_t&lt;T&gt;, charT&gt;&gt; &amp;&amp;
    requires(formatter&lt;remove_cvref_t&lt;T&gt;, charT&gt; f,
             const formatter&lt;remove_cvref_t&lt;T&gt;, charT&gt; cf,
             T t,
             basic_format_context&lt;<i>fmt-iter-for</i>&lt;charT&gt;, charT&gt; fc,
             basic_format_parse_context&lt;charT&gt; pc) {
        { f.parse(pc) } -&gt; same_as&lt;basic_format_parse_context&lt;charT&gt;::iterator&gt;;
        { cf.format(t, fc) } -&gt; same_as&lt;<i>fmt-iter-for</i>&lt;charT&gt;&gt;;
    };</del>
    <ins><i>formattable-with</i>&lt;remove_reference_t&lt;T>, basic_format_context&lt;<i>fmt-iter-for</i>&lt;charT&gt;&gt;&gt;;</ins>
</pre></blockquote>

</li>

<li><p>Modify 22.14.8.1 <a href="https://wg21.link/format.arg">[format.arg]</a> as indicated:</p>

<pre>
namespace std {
  template&lt;class Context&gt;
  class basic_format_arg {
  public:
    class handle;

  private:
    using char_type = typename Context::char_type;                              <i>// exposition only</i>

    variant&lt;monostate, bool, char_type,
            int, unsigned int, long long int, unsigned long long int,
            float, double, long double,
            const char_type*, basic_string_view&lt;char_type&gt;,
            const void*, handle&gt; value;                                         <i>// exposition only</i>

    template&lt;class T&gt; explicit basic_format_arg(T&amp;<del>&amp;</del> v) noexcept;                <i>// exposition only</i>
    <del>explicit basic_format_arg(float n) noexcept;                                <i>// exposition only</i></del>
    <del>explicit basic_format_arg(double n) noexcept;                               <i>// exposition only</i></del>
    <del>explicit basic_format_arg(long double n) noexcept;                          <i>// exposition only</i></del>
    <del>explicit basic_format_arg(const char_type* s);                              <i>// exposition only</i></del>

    <del>template&lt;class traits&gt;</del>
      <del>explicit basic_format_arg(</del>
        <del>basic_string_view&lt;char_type, traits&gt; s) noexcept;                       <i>// exposition only</i></del>

    <del>template&lt;class traits, class Allocator&gt;</del>
      <del>explicit basic_format_arg(</del>
        <del>const basic_string&lt;char_type, traits, Allocator>&amp; s) noexcept;          <i>// exposition only</i></del>

    <del>explicit basic_format_arg(nullptr_t) noexcept;                              <i>// exposition only</i></del>

    <del>template&lt;class T&gt;</del>
      <del>explicit basic_format_arg(T* p) noexcept;                                 <i>// exposition only</i></del>
</pre>
&hellip;
<blockquote>
<pre>
template&lt;class T&gt; explicit basic_format_arg(T&amp;<del>&amp;</del> v) noexcept;
</pre>
<blockquote>
<p>
-4- <i>Constraints:</i>
<ins><tt>T</tt> satisfies <tt><i>formattable-with</i>&lt;Context&gt;</tt>.</ins>
<del>The template specialization</del>
</p>
<blockquote><pre><del>
typename Context::template formatter_type&lt;remove_cvref_t&lt;T&gt;&gt;
</del></pre></blockquote>
<p><del>
meets the <i>BasicFormatter</i> requirements (22.14.6.1 <a href="https://wg21.link/formatter.requirements">[formatter.requirements]</a>). The extent to
which an implementation determines that the specialization meets the <i>BasicFormatter</i>
requirements is unspecified, except that as a minimum the expression
</del></p>
<blockquote><pre><del>
typename Context::template formatter_type&lt;remove_cvref_t&lt;T&gt;&gt;()
  .format(declval&lt;T&amp;&gt;(), declval&lt;Context&amp;&gt;())
</del></pre></blockquote>
<p><del>
shall be well-formed when treated as an unevaluated operand (7.2.3 <a href="https://wg21.link/expr.context">[expr.context]</a>).
</del></p>
<p><ins>-?- <i>Preconditions</i>:
If <tt>decay_t&lt;T&gt;</tt> is <tt>char_type*</tt> or <tt>const char_type*</tt>,
<tt>static_cast&lt;const char_type*&gt;(v)</tt> points to a NTCTS
(3.36 <a href="https://wg21.link/defns.ntcts">[defns.ntcts]</a>).</ins>
</p>
<p>
-5- <i>Effects:</i>
<ins>Let <tt>TD</tt> be <tt>remove_const_t&lt;T&gt;</tt>.</ins>
</p>
<ol style="list-style-type:none">
<li><p>(5.1) &mdash; <ins>If</ins> <del>if</del> <tt>T<ins>D</ins></tt> is <tt>bool</tt> or <tt>char_type</tt>, initializes <tt>value</tt> with <tt>v</tt>;</p></li>
<li><p>(5.2) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is <tt>char</tt> and <tt>char_type</tt> is <tt>wchar_t</tt>,
initializes <tt>value</tt> with <tt>static_cast&lt;wchar_t&gt;(v)</tt>;</p></li>
<li><p>(5.3) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is a signed integer type (6.8.2 <a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a>) and
<tt>sizeof(T<ins>D</ins>) &lt;= sizeof(int)</tt>, initializes <tt>value</tt> with <tt>static_cast&lt;int&gt;(v)</tt>;</p></li>
<li><p>(5.4) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is an unsigned integer type and <tt>sizeof(T<ins>D</ins>) &lt;= sizeof(unsigned int)</tt>,
initializes <tt>value</tt> with <tt>static_cast&lt;unsigned int&gt;(v)</tt>;</p></li>
<li><p>(5.5) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is a signed integer type and <tt>sizeof(T<ins>D</ins>) &lt;= sizeof(long long int)</tt>,
initializes <tt>value</tt> with <tt>static_cast&lt;long long int&gt;(v)</tt>;</p></li>
<li><p>(5.6) &mdash; otherwise, if <tt>T<ins>D</ins></tt> is an unsigned integer type and <tt>sizeof(T<ins>D</ins>) &lt;= sizeof(unsigned long long int)</tt>, initializes <tt>value</tt> with <tt>static_cast&lt;unsigned long long int&gt;(v)</tt>;</p></li>

<li><p><ins>(5.?) &mdash; otherwise, if <tt>TD</tt> is a standard floating-point type, initializes <tt>value</tt> with <tt>v</tt>;</ins></p></li>

<li><p><ins>(5.?) &mdash; otherwise, if <tt>TD</tt> is a specialization of
<tt>basic_string_view</tt> or <tt>basic_string</tt> and <tt>TD::value_type</tt> is <tt>char_type</tt>, initializes <tt>value</tt> with <tt>basic_string_view&lt;char_type&gt;(v.data(), v.size())</tt>;</ins></p></li>

<li><p><ins>(5.?) &mdash; otherwise, if <tt>decay_t&lt;TD&gt;</tt> is <tt>char_type*</tt> or <tt>const char_type*</tt>, initializes <tt>value</tt> with <tt>static_cast&lt;const char_type*&gt;(v)</tt>;</ins></p></li>

<li><p><ins>(5.?) &mdash; otherwise, if <tt>is_void_v&lt;remove_pointer_t&lt;TD&gt;&gt;</tt> is <tt>true</tt> or <tt>is_null_pointer_v&lt;TD&gt;</tt> is <tt>true</tt>, initializes <tt>value</tt> with <tt>static_cast&lt;const void*&gt;(v)</tt>;</ins></p></li>

<li><p>(5.7) &mdash; otherwise, initializes <tt>value</tt> with <tt>handle(v)</tt>.</p></li>
</ol>
<p><ins>-?- [<i>Note</i>: Constructing <tt>basic_format_arg</tt> from a pointer
to a member is ill-formed unless the user provides an enabled specialization
of <tt>formatter</tt> for that pointer to member type. &mdash; <i>end note</i>]
</ins></p>
</blockquote>

<pre><del>
explicit basic_format_arg(float n) noexcept;
explicit basic_format_arg(double n) noexcept;
explicit basic_format_arg(long double n) noexcept;
</del></pre>
<blockquote>
<p><del>-6- <i>Effects</i>: Initializes <tt>value</tt> with <tt>n</tt>.</del></p>
</blockquote>

<pre><del>
explicit basic_format_arg(const char_type* s) noexcept;
</del></pre>
<blockquote>
<p><del>-7- <i>Preconditions</i>: <tt>s</tt> points to a NTCTS (3.36 <a href="https://wg21.link/defns.ntcts">[defns.ntcts]</a>).</del></p>
<p><del>-8- <i>Effects</i>: Initializes <tt>value</tt> with <tt>s</tt>.</del></p>
</blockquote>

<pre><del>
template&lt;class traits&gt;>
  explicit basic_format_arg(basic_string_view&lt;char_type, traits&gt; s) noexcept;
</del></pre>
<blockquote>
<p><del>-9- <i>Effects</i>: Initializes <tt>value</tt> with <tt>basic_string_view&lt;char_type&gt;(s.data(), s.size())</tt>.</del></p>
</blockquote>

<pre><del>
template&lt;class traits, class Allocator&gt;>
  explicit basic_format_arg(
    const basic_string&lt;char_type, traits, Allocator&gt;&amp; s) noexcept;
</del></pre>
<blockquote>
<p><del>-10- <i>Effects</i>: Initializes <tt>value</tt> with <tt>basic_string_view&lt;char_type&gt;(s.data(), s.size())</tt>.</del></p>
</blockquote>

<pre><del>
explicit basic_format_arg(nullptr_t) noexcept;
</del></pre>
<blockquote>
<p><del>-11- <i>Effects</i>: Initializes <tt>value</tt> with <tt>static_cast&lt;const void*&gt;(nullptr)</tt>.</del></p>
</blockquote>

<pre><del>
template&lt;class T&gt; explicit basic_format_arg(T* p) noexcept;
</del></pre>
<blockquote>
<p><del>-12- <i>Constraints</i>: <tt>is_void_v&lt;T&gt;</tt> is <tt>true</tt>.</del></p>
<p><del>-13- <i>Effects</i>: Initializes <tt>value</tt> with <tt>p</tt>.</del></p>
<p><del>-14- <i>[Note</i>: Constructing <tt>basic_format_arg</tt> from a pointer
to a member is ill-formed unless the user provides an enabled specialization
of <tt>formatter</tt> for that pointer to member type. &mdash; <i>end note]</i>
</del></p>
</blockquote>

</blockquote>
</li>

<li><p>Modify 22.14.8.1 <a href="https://wg21.link/format.arg">[format.arg]</a> p17 and p18 as indicated:</p>

<blockquote>
<pre>
template&lt;class T&gt; explicit handle(T&amp;<del>&amp;</del> v) noexcept;
</pre>
<blockquote>
<p>-17- Let</p>
<ol style="list-style-type:none">
<li><p>&mdash; (17.1)
<tt>TD</tt> be <tt>remove_<del>cvref</del><ins>const</ins>_t&lt;T&gt;</tt>,
</p></li>
<li><p><del>&mdash; (17.2)
<tt><i>const-formattable</i></tt> be <tt>true</tt> if
<tt>typename Context::template formatter_type&lt;TD&gt;().format(declval&lt;const TD&amp;&gt;(), declval&lt;Context&amp;&gt;())</tt>
is well-formed, otherwise <tt>false</tt>,</del>
</p></li>
<li><p>&mdash; (17.3)
<tt>TQ</tt> be <tt>const TD</tt> if
<del><tt><i>const-formattable</i></tt> is <tt>true</tt></del>
<ins><tt>const TD</tt> satisfies <tt><i>formattable-with</i>&lt;Context&gt;</tt></ins>
and <tt>TD</tt> otherwise.
</p></li>
</ol>
<p>-18- <i>Mandates</i>:
<del><tt><i>const-formattable</i>
|| !is_const_v&lt;remove_reference_t&lt;T&gt;&gt;</tt> is <tt>true</tt>.</del>
<ins><tt>TQ</tt> satisfies <tt><i>formattable-with</i>&lt;Context&gt;</tt>.</ins>
</p>
<p>-19- <i>Effects</i>:
Initializes <tt>ptr_</tt> with <tt>addressof(val)</tt> and <tt>format_</tt> with
<blockquote><pre>
[](basic_format_parse_context&lt;char_type&gt;&amp; parse_ctx,
   Context&amp; format_ctx, const void* ptr) {
  typename Context::template formatter_type&lt;TD&gt; f;
  parse_ctx.advance_to(f.parse(parse_ctx));
  format_ctx.advance_to(f.format(*const_cast&lt;TQ*&gt;(static_cast&lt;const TD*&gt;(ptr)),
                                 format_ctx));
}
</pre></blockquote>
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 22.14.8.2 <a href="https://wg21.link/format.arg.store">[format.arg.store]</a> p2 as indicated:</p>

<blockquote>
<pre>
template&lt;class Context = format_context, class... Args&gt;
  <i>format-arg-store</i>&lt;Context, Args...&gt; make_format_args(Args&amp;&amp;... fmt_args);
</pre>
<blockquote>
<p>-2- <i>Preconditions</i>: The type
<tt>typename Context::template formatter_type&lt;<ins>remove_cvref_t&lt;</ins>T</tt><sub>i</sub><tt><ins>&gt;</ins>&gt;</tt>
meets the <i>BasicFormatter</i> requirements (22.14.6.1 <a href="https://wg21.link/formatter.requirements">[formatter.requirements]</a>) for each <tt>T</tt><sub>i</sub>
in <tt>Args</tt>.
</p>
</blockquote>
</blockquote>

</li>
</ol>







<hr>
<h3><a name="3645" href="https://cplusplus.github.io/LWG/lwg-active.html#3645">3645</a>. <tt>resize_and_overwrite</tt> is overspecified to call its callback with lvalues</h3>
<p><b>Section:</b> 23.4.3.5 <a href="https://wg21.link/string.capacity">[string.capacity]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Arthur O'Dwyer <b>Opened:</b> 2021-11-28 <b>Last modified:</b> 2023-02-09</p>
<p><b>Priority: </b>2
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#string.capacity">issues</a> in [string.capacity].</p>
<p><b>Discussion:</b></p>
<p>
23.4.3.5 <a href="https://wg21.link/string.capacity">[string.capacity]</a> p7 says:
</p>
<ul>
<li><p>[Let] <tt><i>OP</i></tt> be the expression <tt>std::move(op)(p, n)</tt>.</p></li>
<li><p>[<i>Precondition:</i>] <tt><i>OP</i></tt> does not throw an exception or modify <tt>p</tt> or <tt>n</tt>.</p></li>
</ul>
<p>
Notice that <tt>p</tt> and <tt>n</tt> above are lvalue expressions.
<p/>
Discussed with Mark Zeren, Casey Carter, Jonathan Wakely. We observe that:
<p/>
A. This wording requires vendors to reject
</p>
<blockquote><pre>
s.resize_and_overwrite(100, [](char*&amp;&amp;, size_t&amp;&amp;){ return 0; });
</pre></blockquote>
<p>
which is surprising.
<p/>
B. This wording requires vendors to accept
</p>
<blockquote><pre>
s.resize_and_overwrite(100, [](char*&amp;, size_t&amp;){ return 0; });
</pre></blockquote>
<p>
which is even more surprising, and also threatens to allow the user to corrupt 
the internal state (which is why we need to specify the Precondition above).
<p/>
C. A user who writes
</p>
<blockquote><pre>
s.resize_and_overwrite(100, [](auto&amp;&amp;, auto&amp;&amp;){ return 0; });
</pre></blockquote>
<p>
can detect that they're being passed lvalues instead of rvalues. If we change 
the wording to permit implementations to pass either lvalues or rvalues (their choice), 
then this will be detectable by the user, so we don't want that if we can help it.
</p>
<ol style="list-style-type:none">
<li><p>X. We want to enable implementations to say <tt>move(op)(__p, __n)</tt> 
and then use <tt>__p</tt> and <tt>__n</tt>.</p></li>
<li><p>Y. We have one implementation which wants to say <tt>move(op)(data(), __n)</tt>, 
which is not currently allowed, but arguably should be.</p></li>
<li><p>Z. We have to do or say something about disallowing writes to any 
internal state to which <tt>Op</tt> might get a reference.</p></li>
</ol>
<p>
Given all of this, Mark and Arthur think that the simplest way out is to say that the 
arguments are prvalues. It prevents X, but fixes the surprises in A, B, Y, Z. We 
could do this in the Let bullets. Either like so:
</p>
<ul>
<li><p>[Let] <tt>p</tt> be a prvalue of type <tt>charT*</tt> &hellip;</p></li>
<li><p><tt>m</tt> be a prvalue of type <tt>size_type</tt> equal to <tt>n</tt>,</p></li>
<li><p><tt><i>OP</i></tt> be the expression <tt>std::move(op)(p, m)</tt>.</p></li>
</ul>
<p>
or (Arthur's preference) by specifying prvalues in the expression <tt><i>OP</i></tt> itself:
</p>
<ul>
<li><p>[Let] <tt><i>OP</i></tt> be the expression <tt>std::move(op)(auto(p), auto(n))</tt>.</p></li>
</ul>
<p>
No matter which specification approach we adopt, we can also simplify the Preconditions bullet to:
</p>
<ul>
<li><p>[<i>Precondition:</i>] <tt><i>OP</i></tt> does not throw an exception.</p></li>
</ul>
<p>
because once the user is receiving prvalue copies, it will no longer be physically possible for the 
user to modify the library's original variables <tt>p</tt> and <tt>n</tt>.
</p>

<p><i>[2021-11-29; Arthur O'Dwyer provides wording]</i></p>


<p><i>[2022-01-30; Reflector poll]</i></p>

<p>
Set priority to 2 after reflector poll.
</p>

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

<ol>

<li><p>Modify 23.4.3.5 <a href="https://wg21.link/string.capacity">[string.capacity]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class Operation&gt; constexpr void resize_and_overwrite(size_type n, Operation op);
</pre>
<blockquote>
<p>
-7- Let
</p>
<ol style="list-style-type:none">
<li><p>(7.1) &mdash; <tt>o = size()</tt> before the call to <tt>resize_and_overwrite</tt>.</p></li>
<li><p>(7.2) &mdash; <tt>k</tt> be <tt>min(o, n)</tt>.</p></li>
<li><p>(7.3) &mdash; <tt>p</tt> be a <tt>charT*</tt>, such that the range <tt>[p, p + n]</tt> is valid 
and <tt>this-&gt;compare(0, k, p, k) == 0</tt> is <tt>true</tt> before the call. The values in the range 
<tt>[p + k, p + n]</tt> may be indeterminate (6.7.4 <a href="https://wg21.link/basic.indet">[basic.indet]</a>).</p></li>
<li><p>(7.4) &mdash; <tt><i>OP</i></tt> be the expression <tt>std::move(op)(<ins>auto(</ins>p<ins>)</ins>, <ins>auto(</ins>n<ins>)</ins>)</tt>.</p></li>
<li><p>(7.5) &mdash; <tt>r = <i>OP</i></tt>.</p></li>
</ol>
<p>
-8- <i>Mandates:</i> <tt><i>OP</i></tt> has an integer-like type (25.3.4.4 <a href="https://wg21.link/iterator.concept.winc">[iterator.concept.winc]</a>).
<p/>
-9- <i>Preconditions:</i>
</p>
<ol style="list-style-type:none">
<li><p>(9.1) &mdash; <tt><i>OP</i></tt> does not throw an exception <del>or modify <tt>p</tt> or <tt>n</tt></del>.</p></li>
<li><p>(9.2) &mdash; <tt>r &ge; 0</tt>.</p></li>
<li><p>(9.3) &mdash; <tt>r &le; n</tt>.</p></li>
<li><p>(9.4) &mdash; After evaluating <tt><i>OP</i></tt> there are no indeterminate values in the range 
<tt>[p, p + r)</tt>.</p></li>
</ol>
<p>
-10- <i>Effects:</i> Evaluates <tt><i>OP</i></tt>, replaces the contents of <tt>*this</tt> with <tt>[p, p + r)</tt>, 
and invalidates all pointers and references to the range <tt>[p, p + n]</tt>.
<p/>
-11- <i>Recommended practice:</i> Implementations should avoid unnecessary copies and allocations by, for example,
making <tt>p</tt> a pointer into internal storage and by restoring <tt>*(p + r)</tt> to <tt>charT()</tt> 
after evaluating <tt><i>OP</i></tt>.
</p>
</blockquote>
</blockquote>
</li>

</ol>
</blockquote>

<p><i>[2023-01-11; Jonathan Wakely provides new wording requested by LWG]</i></p>


<p><i>[Issaquah 2023-02-07; LWG]</i></p>

<p>Move to Immediate for C++23</p>



<p id="res-3645"><b>Proposed resolution:</b></p>

<p>
This wording is relative to <a href="https://wg21.link/N4917">N4917</a>.
</p>

<ol>

<li><p>Modify 23.4.3.5 <a href="https://wg21.link/string.capacity">[string.capacity]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class Operation&gt; constexpr void resize_and_overwrite(size_type n, Operation op);
</pre>
<blockquote>
<p>
-7- Let
</p>
<ol style="list-style-type:none">
<li><p>(7.1) &mdash; <tt>o = size()</tt> before the call to <tt>resize_and_overwrite</tt>.</p></li>
<li><p>(7.2) &mdash; <tt>k</tt> be <tt>min(o, n)</tt>.</p></li>
<li><p>(7.3) &mdash; <tt>p</tt> be a <ins>value of type</ins>
<tt>charT*</tt> <ins>or <tt>charT* const</tt></ins>,
such that the range <tt>[p, p + n]</tt> is valid
and <tt>this-&gt;compare(0, k, p, k) == 0</tt> is <tt>true</tt> before the call.
The values in the range
<tt>[p + k, p + n]</tt> may be indeterminate (6.7.4 <a href="https://wg21.link/basic.indet">[basic.indet]</a>).</p></li>
<li><p><ins>(7.?) &mdash;
<tt>m</tt> be a value of type <tt>size_type</tt> or
<tt>const size_type</tt> equal to <tt>n</tt>.
</ins></p></li>
<li><p>(7.4) &mdash; <tt><i>OP</i></tt> be the expression <tt>std::move(op)(p, <del>n</del><ins>m</ins>)</tt>.</p></li>
<li><p>(7.5) &mdash; <tt>r = <i>OP</i></tt>.</p></li>
</ol>
<p>
-8- <i>Mandates:</i> <tt><i>OP</i></tt> has an integer-like type (25.3.4.4 <a href="https://wg21.link/iterator.concept.winc">[iterator.concept.winc]</a>).
<p/>
-9- <i>Preconditions:</i>
</p>
<ol style="list-style-type:none">
<li><p>(9.1) &mdash; <tt><i>OP</i></tt> does not throw an exception or modify <tt>p</tt> or <tt><del>n</del><ins>m</ins></tt>.</p></li>
<li><p>(9.2) &mdash; <tt>r &ge; 0</tt>.</p></li>
<li><p>(9.3) &mdash; <tt>r &le; <del>n</del><ins>m</ins></tt>.</p></li>
<li><p>(9.4) &mdash; After evaluating <tt><i>OP</i></tt> there are no indeterminate values in the range
<tt>[p, p + r)</tt>.</p></li>
</ol>
<p>
-10- <i>Effects:</i> Evaluates <tt><i>OP</i></tt>, replaces the contents of <tt>*this</tt> with <tt>[p, p + r)</tt>,
and invalidates all pointers and references to the range <tt>[p, p + n]</tt>.
<p/>
-11- <i>Recommended practice:</i> Implementations should avoid unnecessary copies and allocations by, for example,
making <tt>p</tt> a pointer into internal storage and by restoring <tt>*(p + r)</tt> to <tt>charT()</tt>
after evaluating <tt><i>OP</i></tt>.
</p>
</blockquote>
</blockquote>
</li>

</ol>






<hr>
<h3><a name="3655" href="https://cplusplus.github.io/LWG/lwg-active.html#3655">3655</a>. The <tt><i>INVOKE</i></tt> operation and <tt>union</tt> types</h3>
<p><b>Section:</b> 22.10.4 <a href="https://wg21.link/func.require">[func.require]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Jiang An <b>Opened:</b> 2021-12-29 <b>Last modified:</b> 2023-02-07</p>
<p><b>Priority: </b>3
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#func.require">issues</a> in [func.require].</p>
<p><b>Discussion:</b></p>
<p>
There are two cases of the <tt><i>INVOKE</i></tt> operation specified with <tt>std::is_base_of_v</tt> 
(22.10.4 <a href="https://wg21.link/func.require">[func.require]</a> (1.1), (1,4)), which means the following code snippet is ill-formed, as 
<tt>std::is_base_of_v&lt;B, D&gt;</tt> is <tt>false</tt> when either <tt>B</tt> or <tt>D</tt> is a 
<tt>union</tt> type.
</p>
<blockquote><pre>
union Foo { int x; };
static_assert(std::is_invocable_v&lt;int Foo::*, Foo&amp;&gt;);
</pre></blockquote>
<p>
Currently libstdc++ accepts this code, because it uses slightly different conditions that handle <tt>union</tt> 
types. libc++ and MSVC STL reject this code as specified in 22.10.4 <a href="https://wg21.link/func.require">[func.require]</a>.
<p/>
Should we change the conditions in 22.10.4 <a href="https://wg21.link/func.require">[func.require]</a> (1.1) and (1.4) to match libstdc++ and correctly 
handle <tt>union</tt> types?
</p>

<p><i>[2022-01-30; Reflector poll]</i></p>

<p>
Set priority to 3 after reflector poll.
</p>

<p><i>[2023-02-07; Jonathan adds wording]</i></p>

<p>This is a regression introduced by LWG <a href="https://cplusplus.github.io/LWG/lwg-defects.html#2219">2219</a>.
In C++14 <code>std::result_of&lt;int Foo::*(Foo&amp;)&gt;::type</code>
was valid, because the <tt><i>INVOKE</i></tt> wording used to say
"<tt>f</tt> is a pointer to member data of a class <tt>T</tt>
and <tt>t1</tt> is an object of type <tt>T</tt>
or a reference to an object of type <tt>T</tt>
or a reference to an object of a type derived from <tt>T</tt>".
Since LWG 2219 we use <code>is_base_of</code> which is always false for
union types.
I don't think LWG 2219 intended to break this case, so we should fix it.
</p>

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

<ol>
<li><p>Modify 22.10.4 <a href="https://wg21.link/func.require">[func.require]</a> as indicated:</p>

<blockquote>
<p>-1-
Define <tt><i>INVOKE</i>(f, t1, t2, &hellip;, tN)</tt> as follows:
</p>
<ul>
<li>(1.1) &mdash;
<tt>(t1.*f)(t2, &hellip;, tN)</tt>
when <tt>f</tt> is a pointer to a member function of a class <tt>T</tt> and
<tt>
<ins>is_same_v&lt;T, remove_cvref_t&lt;decltype(t1)&gt;&gt; ||</ins>
is_base_of_v&lt;T, remove_reference_t&lt;decltype(t1)&gt;&gt;</tt>
is <tt>true</tt>;
</li>
<li>(1.2) &mdash;
<tt>(t1.get().*f)(t2, &hellip;, tN)</tt>
when <tt>f</tt> is a pointer to a member function of a class <tt>T</tt> and
<tt>remove_cvref_t&lt;decltype(t1)&gt;</tt>
is a specialization of <tt>reference_wrapper</tt>;
</li>
<li>(1.3) &mdash;
<tt>((*t1).*f)(t2, &hellip;, tN)</tt>
when <tt>f</tt> is a pointer to a member function of a class <tt>T</tt> and
<tt>t1</tt> does not satisfy the previous two items;
</li>
<li>(1.4) &mdash;
<tt>t1.*f</tt>
when <tt>N == 1</tt> and
<tt>f</tt> is a pointer to data member of a class <tt>T</tt> and
<tt>
<ins>is_same_v&lt;T, remove_cvref_t&lt;decltype(t1)&gt;&gt; ||</ins>
is_base_of_v&lt;T, remove_reference_t&lt;decltype(t1)&gt;&gt;</tt>
is <tt>true</tt>;
</li>
<li>(1.5) &mdash;
<tt>t1.get().*f</tt>
when <tt>N == 1</tt> and
<tt>f</tt> is a pointer to data member of a class <tt>T</tt> and
<tt>remove_cvref_t&lt;decltype(t1)&gt;</tt>
is a specialization of <tt>reference_wrapper</tt>;
</li>
<li>(1.6) &mdash;
<tt>(*t1).*f</tt>
when <tt>N == 1</tt> and
<tt>f</tt> is a pointer to data member of a class <tt>T</tt> and
<tt>t1</tt> does not satisfy the previous two items;
</li>
<li>(1.7) &mdash;
<tt>f(t1, t2, &hellip;, tN)</tt> in all other cases.
</li>
</ul>
</blockquote>
</li>
</ol>

</blockquote>

<p><i>[2023-02-07; Jonathan provides wording change requested by LWG]</i></p>

<p>Change <tt>remove_reference_t</tt> to <tt>remove_cvref_t</tt>.
<tt>is_base_of</tt> ignores cv-qualifiers, so this isn't necessary,
but just using the same transformation in both cases seems simpler to grok.
</p>

<p><i>[Issaquah 2023-02-07; LWG]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>
<li><p>Modify 22.10.4 <a href="https://wg21.link/func.require">[func.require]</a> as indicated:</p>

<blockquote>
<p>-1-
Define <tt><i>INVOKE</i>(f, t1, t2, &hellip;, tN)</tt> as follows:
</p>
<ul>
<li>(1.1) &mdash;
<tt>(t1.*f)(t2, &hellip;, tN)</tt>
when <tt>f</tt> is a pointer to a member function of a class <tt>T</tt> and
<tt>
<ins>is_same_v&lt;T, remove_cvref_t&lt;decltype(t1)&gt;&gt; ||</ins>
is_base_of_v&lt;T, remove_<del>reference</del><ins>cvref</ins>_t&lt;decltype(t1)&gt;&gt;</tt>
is <tt>true</tt>;
</li>
<li>(1.2) &mdash;
<tt>(t1.get().*f)(t2, &hellip;, tN)</tt>
when <tt>f</tt> is a pointer to a member function of a class <tt>T</tt> and
<tt>remove_cvref_t&lt;decltype(t1)&gt;</tt>
is a specialization of <tt>reference_wrapper</tt>;
</li>
<li>(1.3) &mdash;
<tt>((*t1).*f)(t2, &hellip;, tN)</tt>
when <tt>f</tt> is a pointer to a member function of a class <tt>T</tt> and
<tt>t1</tt> does not satisfy the previous two items;
</li>
<li>(1.4) &mdash;
<tt>t1.*f</tt>
when <tt>N == 1</tt> and
<tt>f</tt> is a pointer to data member of a class <tt>T</tt> and
<tt>
<ins>is_same_v&lt;T, remove_cvref_t&lt;decltype(t1)&gt;&gt; ||</ins>
is_base_of_v&lt;T, remove_<del>reference</del><ins>cvref</ins>_t&lt;decltype(t1)&gt;&gt;</tt>
is <tt>true</tt>;
</li>
<li>(1.5) &mdash;
<tt>t1.get().*f</tt>
when <tt>N == 1</tt> and
<tt>f</tt> is a pointer to data member of a class <tt>T</tt> and
<tt>remove_cvref_t&lt;decltype(t1)&gt;</tt>
is a specialization of <tt>reference_wrapper</tt>;
</li>
<li>(1.6) &mdash;
<tt>(*t1).*f</tt>
when <tt>N == 1</tt> and
<tt>f</tt> is a pointer to data member of a class <tt>T</tt> and
<tt>t1</tt> does not satisfy the previous two items;
</li>
<li>(1.7) &mdash;
<tt>f(t1, t2, &hellip;, tN)</tt> in all other cases.
</li>
</ul>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3723" href="https://cplusplus.github.io/LWG/lwg-active.html#3723">3723</a>. <tt>priority_queue::push_range</tt> needs to <tt>append_range</tt></h3>
<p><b>Section:</b> 24.6.7.4 <a href="https://wg21.link/priqueue.members">[priqueue.members]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Casey Carter <b>Opened:</b> 2022-06-20 <b>Last modified:</b> 2023-02-08</p>
<p><b>Priority: </b>2
</p>
<p><b>Discussion:</b></p>
<p>
The <tt>push_range</tt> members of the <tt>queue</tt> (24.6.6.4 <a href="https://wg21.link/queue.mod">[queue.mod]</a>) and 
<tt>stack</tt> (24.6.8.5 <a href="https://wg21.link/stack.mod">[stack.mod]</a>) container adaptors are both specified as 
"<i>Effects</i>: Equivalent to <tt>c.append_range(std::forward&lt;R&gt;(rg))</tt> if that 
is a valid expression, otherwise <tt>ranges::copy(rg, back_inserter(c))</tt>.". For 
<tt>priority_queue</tt>, however, we have instead (24.6.7.4 <a href="https://wg21.link/priqueue.members">[priqueue.members]</a>):
</p>
<blockquote><p>
-3- <i>Effects</i>: Insert all elements of <tt>rg</tt> in <tt>c</tt>.
<p/>
-4- <i>Postconditions</i>: <tt>is_heap(c.begin(), c.end(), comp)</tt> is <tt>true</tt>.
</p></blockquote>
<p>
Since <tt>append_range</tt> isn't one of the operations required of the underlying container, 
"Insert all elements of <tt>rg</tt>" must be implemented via potentially less efficient means. 
It would be nice if this <tt>push_back</tt> could take advantage of <tt>append_range</tt> 
when it's available just as do the other two overloads.
</p>

<p><i>[2022-07-08; Reflector poll]</i></p>

<p>
Set priority to 2 after reflector poll.
</p>

<p><i>[Issaquah 2023-02-08; LWG]</i></p>

<p>Unanimous consent to move to Immediate.</p>



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

<ol>
<li><p>Modify 24.6.7.4 <a href="https://wg21.link/priqueue.members">[priqueue.members]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;<i>container-compatible-range</i>&lt;T&gt; R&gt;
  void push_range(R&amp;&amp; rg);
</pre>
<blockquote>
<p>
-3- <i>Effects</i>: Insert<ins>s</ins> all elements of <tt>rg</tt> in <tt>c</tt> <ins>via 
<tt>c.append_range(std::forward&lt;R&gt;(rg))</tt> if that is a valid expression, or 
<tt>ranges::copy(rg, back_inserter(c))</tt> otherwise. Then restores the heap property as if 
by <tt>make_heap(c.begin(), c.end(), comp)</tt></ins>.
<p/>
-4- <i>Postconditions</i>: <tt>is_heap(c.begin(), c.end(), comp)</tt> is <tt>true</tt>. 
</p>
</blockquote>
</blockquote>
</li>

</ol>





<hr>
<h3><a name="3734" href="https://cplusplus.github.io/LWG/lwg-active.html#3734">3734</a>. Inconsistency in <tt>inout_ptr</tt> and <tt>out_ptr</tt> for empty case</h3>
<p><b>Section:</b> 20.3.4.1 <a href="https://wg21.link/out.ptr.t">[out.ptr.t]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Doug Cook <b>Opened:</b> 2022-07-11 <b>Last modified:</b> 2023-02-09</p>
<p><b>Priority: </b>2
</p>
<p><b>Discussion:</b></p>
<p>
<tt>out_ptr</tt> and <tt>inout_ptr</tt> are inconsistent when a pointer-style function returns 
<tt>nullptr</tt>.
</p>
<ul>
<li><p><tt>out_ptr</tt> leaves the stale value in <tt>smart</tt> (not the value returned by the pointer-style function).</p></li>
<li><p><tt>inout_ptr</tt> (as resolved by LWG <a href="https://cplusplus.github.io/LWG/lwg-defects.html#3594">3594</a>) leaves <tt>nullptr</tt> in <tt>smart</tt> (the value 
returned by the pointer-style function).</p></li>
</ul>
<p>
Assume we have the following pointer-style functions that return <tt>nullptr</tt> in case of failure:
</p>
<blockquote><pre>
void ReplaceSomething(/*INOUT*/ int** pp) {
  delete *pp;
  *pp = nullptr;
  return; // <span style="color:red;font-weight:bolder">Failure!</span>
} 

void GetSomething(/*OUT*/ int** pp) {
  *pp = nullptr;
  return; // <span style="color:red;font-weight:bolder">Failure!</span>
}
</pre></blockquote>
<p>
In the scenario that led to the creation of issue LWG <a href="https://cplusplus.github.io/LWG/lwg-defects.html#3594">3594</a>:
</p>
<blockquote><pre>
// Before the call, inout contains a stale value.
auto inout = std::make_unique&lt;int&gt;(1);
ReplaceSomething(std::inout_ptr(inout));
// (1) If ReplaceSomething failed (returned nullptr), what does inout contain?
</pre></blockquote>
<p>
Assuming LWG <a href="https://cplusplus.github.io/LWG/lwg-defects.html#3594">3594</a> is resolved as suggested, <tt>inout</tt> will be empty. 
(The original <a href="https://wg21.link/N4901">N4901</a> text allows <tt>inout</tt> to be either empty or 
to hold a pointer to already-deleted memory.) Using the resolution suggested by 
LWG <a href="https://cplusplus.github.io/LWG/lwg-defects.html#3594">3594</a>, it expands to something like the following (simplified to 
ignore exceptions and opting to perform the <tt>release()</tt> before the 
<tt>ReplaceSomething()</tt> operation): 
</p>
<blockquote><pre>
// Before the call, inout contains a stale value.
auto inout = std::make_unique&lt;int&gt;(1);
int* p = inout.release();
ReplaceSomething(&amp;p);
if (p) {
  inout.reset(p);
}
// (1) If ReplaceSomething failed (returned nullptr), inout contains nullptr.
</pre></blockquote>
<p>
This behavior seems reasonable.
<p/>
Now consider the corresponding scenario with <tt>out_ptr</tt>:
</p>
<blockquote><pre>
// Before the call, out contains a stale value.
auto out = std::make_unique&lt;int&gt;(2);
GetSomething(std::out_ptr(out));
// (2) If GetSomething failed (returned nullptr), what does out contain? 
</pre></blockquote>
<p>
Based on <a href="https://wg21.link/N4901">N4901</a>, <tt>out</tt> contains the stale value (from 
<tt>make_unique</tt>), not the <tt>nullptr</tt> value returned by <tt>GetSomething()</tt>. 
The <a href="https://wg21.link/N4901">N4901</a> model (simplified to ignore exceptions) expands to the following:
</p>
<blockquote><pre>
// Before the call, out contains a stale value.
auto out = std::make_unique&lt;int&gt;(2);
int* p{};
GetSomething(&amp;p);
if (p) {
  out.reset(p);
}
// (2) If GetSomething failed (returned nullptr), out contains a pointer to "2".
</pre></blockquote>
<p>
This behavior seems incorrect to me. It is inconsistent with the behavior of <tt>inout_ptr</tt> 
and it is inconsistent with my expectation that <tt>out</tt> should contain the value returned 
by <tt>GetSomething()</tt>, even if that value is <tt>nullptr</tt>. Intuitively, I expect it to 
behave as if the <tt>out.reset(p)</tt> were unconditional.
<p/>
The <tt>reset(p)</tt> is conditional as an optimization for cases where <tt>reset</tt> is 
non-trivial. For example, <tt>shared_ptr</tt>'s <tt>reset(p)</tt> requires the allocation of 
a control block even if <tt>p</tt> is <tt>nullptr</tt>. As such, simply making the <tt>reset</tt> 
unconditional may be sub-optimal.
<p/>
I see two primary options for making <tt>out_ptr</tt>'s behavior consistent with <tt>inout_ptr</tt>:
</p> 
<ul>
<li><p>Perform an unconditional <tt>out.reset()</tt> or <tt>out = Smart()</tt> in the <tt>out_ptr_t</tt> 
constructor.</p></li>
<li><p>Add an else clause to the if statement, containing <tt>out.reset()</tt> or <tt>out = Smart()</tt>.</p></li>
</ul>
<p>
I note that these solutions do not make use of the additional <tt>args...</tt>, leaving the 
<tt>out</tt> pointer in an empty state. This is analogous to the corresponding state in the similar 
<tt>inout</tt> scenario where the <tt>inout</tt> pointer is left empty as a result of the call to 
<tt>smart.release()</tt>.
<p/>
I favor the first resolution, freeing any existing value in the <tt>out_ptr_t</tt> constructor.
</p>

<p><i>[2022-08-23; Reflector poll]</i></p>

<p>
Set priority to 2 after reflector poll. "A bit like design."
</p>

<p><i>[Issaquah 2023-02-07; LWG]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>

<li><p>Modify 20.3.4.1 <a href="https://wg21.link/out.ptr.t">[out.ptr.t]</a> as indicated:</p>

<blockquote>
<pre>
explicit out_ptr_t(Smart&amp; smart, Args... args);
</pre>
<blockquote>
<p>
-6- <i>Effects:</i> Initializes <tt>s</tt> with <tt>smart</tt>, <tt>a</tt> with 
<tt>std::forward&lt;Args&gt;(args)...</tt>, and value-initializes 
<tt>p</tt>. <ins>Then, equivalent to:</ins>
</p>
<ul>
<li><ins>(6.1) &mdash;</ins><blockquote><pre><ins>s.reset();</ins></pre></blockquote>
<p><ins>if the expression <tt>s.reset()</tt> is well-formed;</ins></p></li>
<li><p><ins>(6.2) &mdash; otherwise,</ins></p>
<blockquote><pre>
<ins>s = Smart();</ins>
</pre></blockquote>
<p><ins>if <tt>is_constructible_v&lt;Smart&gt;</tt> is <tt>true</tt>;</ins></p></li>
<li><p><ins>(6.3) &mdash; otherwise, the program is ill-formed.</ins></p></li>
</ul>
<p>
-7- [<i>Note 2</i>: The constructor is not <tt>noexcept</tt> to allow for a variety of 
non-terminating and safe implementation strategies. For example, an implementation can 
allocate a <tt>shared_ptr</tt>'s internal node in the constructor and let 
implementation-defined exceptions escape safely. The destructor can then move the allocated 
control block in directly and avoid any other exceptions. &mdash; <i>end note</i>]
</p>
</blockquote>
</blockquote>
</li>


</ol>





<hr>
<h3><a name="3772" href="https://cplusplus.github.io/LWG/lwg-active.html#3772">3772</a>. <tt>repeat_view</tt>'s piecewise constructor is missing <i>Postconditions</i></h3>
<p><b>Section:</b> 26.6.5.2 <a href="https://wg21.link/range.repeat.view">[range.repeat.view]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2022-09-12 <b>Last modified:</b> 2023-02-09</p>
<p><b>Priority: </b>2
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#range.repeat.view">issues</a> in [range.repeat.view].</p>
<p><b>Discussion:</b></p>
<p>
The first two value-bound pair constructors of <tt>repeat_view</tt> have the
<i>Preconditions</i> that the integer-like object <tt>bound</tt> must be
non-negative.
However, the piecewise constructor does not mention the valid values for
<tt>bound_args</tt>.
It would be nice to add a <i>Postconditions</i> that the initialized
<tt>bound_</tt> must be greater than or equal to <tt>0</tt> here.
</p>

<p><i>[2022-09-23; Reflector poll]</i></p>

<p>
Set priority to 2 after reflector poll.
</p>
<p>
This is trying to state a requirement on users, but that's not what
<i>Postconditions:</i> means. Should be something more like:
<br/>
Precondition: If <tt>Bound</tt> is not <tt>unreachable_sentinel_t</tt>,
the  <tt>bound_</tt> &ge; 0 after its initialization from <tt>bound_args</tt>.
</p>

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

<ol>
<li>
<p>Modify 26.6.5.2 <a href="https://wg21.link/range.repeat.view">[range.repeat.view]</a> as shown:</p>

<blockquote>
<pre>
template&lt;class... WArgs, class... BoundArgs&gt;
  requires constructible_from&lt;W, WArgs...&gt; &amp;&amp;
           constructible_from&lt;Bound, BoundArgs...&gt;
constexpr explicit repeat_view(piecewise_construct_t,
  tuple&lt;Wargs...&gt; value_args, tuple&lt;BoundArgs...&gt; bound_args = tuple&lt;&gt;{});
</pre>

<blockquote>
<p>
-5- <i>Effects</i>: Initializes <tt><i>value_</i></tt> with arguments of types <tt>WArgs...</tt> obtained by forwarding the elements of <tt>value_args</tt> and initializes <tt><i>bound_</i></tt> 
with arguments of types <tt>BoundArgs...</tt> obtained by forwarding the elements of <tt>bound_args</tt>. (Here, forwarding an element <tt>x</tt> of type <tt>U</tt> within a tuple object means calling <tt>std::forward&lt;U&gt;(x)</tt>.)  
</p>
<p>
<ins>-?- <i>Postconditions</i>: If <tt>Bound</tt> is not <tt>unreachable_sentinel_t</tt>, <tt><i>bound_</i></tt> &ge; 0.</ins>
</p>
</blockquote>
</blockquote>
</li>
</ol>

</blockquote>

<p><i>[2022-09-23; Jonathan provides improved wording]</i></p>


<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">

<p>
This wording is relative to <a href="https://wg21.link/N4917">N4917</a>.
</p>

<ol>
<li>
<p>Modify 26.6.5.2 <a href="https://wg21.link/range.repeat.view">[range.repeat.view]</a> as shown:</p>

<blockquote>
<pre>
template&lt;class... WArgs, class... BoundArgs&gt;
  requires constructible_from&lt;W, WArgs...&gt; &amp;&amp;
           constructible_from&lt;Bound, BoundArgs...&gt;
constexpr explicit repeat_view(piecewise_construct_t,
  tuple&lt;Wargs...&gt; value_args, tuple&lt;BoundArgs...&gt; bound_args = tuple&lt;&gt;{});
</pre>

<blockquote>
<p>
<ins>-?- <i>Preconditions</i>:
<tt>Bound</tt> is <tt>unreachable_sentinel_t</tt>,
or the initialization of <tt><i>bound_</i></tt> yields a non-negative value.
</ins>
</p>
<p>
-5- <i>Effects</i>: Initializes <tt><i>value_</i></tt> with arguments of types <tt>WArgs...</tt> obtained by forwarding the elements of <tt>value_args</tt> and initializes <tt><i>bound_</i></tt>
with arguments of types <tt>BoundArgs...</tt> obtained by forwarding the elements of <tt>bound_args</tt>. (Here, forwarding an element <tt>x</tt> of type <tt>U</tt> within a tuple object means calling <tt>std::forward&lt;U&gt;(x)</tt>.)
</p>
</blockquote>
</blockquote>
</li>
</ol>

</blockquote>

<p><i>[2023-01-11; Jonathan provides new wording requested by LWG]</i></p>


<p><i>[Issaquah 2023-02-07; LWG]</i></p>

<p>Move to Immediate for C++23</p>



<p id="res-3772"><b>Proposed resolution:</b></p>

<p>
This wording is relative to <a href="https://wg21.link/N4917">N4917</a>.
</p>

<ol>
<li>
<p>Modify 26.6.5.2 <a href="https://wg21.link/range.repeat.view">[range.repeat.view]</a> as shown:</p>

<blockquote>
<pre>
template&lt;class... TArgs, class... BoundArgs&gt;
  requires constructible_from&lt;T, TArgs...&gt; &amp;&amp;
           constructible_from&lt;Bound, BoundArgs...&gt;
constexpr explicit repeat_view(piecewise_construct_t,
  tuple&lt;Targs...&gt; value_args, tuple&lt;BoundArgs...&gt; bound_args = tuple&lt;&gt;{});
</pre>

<blockquote>
<p>
-5- <i>Effects</i>: Initializes <tt><i>value_</i></tt> with
<del>arguments of types <tt>TArgs...</tt> obtained by
forwarding the elements of <tt>value_args</tt></del>
<ins><tt>make_from_tuple&lt;T&gt;(std::move(value_args))</tt></ins>
and initializes <tt><i>bound_</i></tt>
with
<del>arguments of types <tt>BoundArgs...</tt> obtained by forwarding the elements of <tt>bound_args</tt>. (Here, forwarding an element <tt>x</tt> of type <tt>U</tt> within a tuple object means calling <tt>std::forward&lt;U&gt;(x)</tt>.)
</del>
<ins><tt>make_from_tuple&lt;Bound&gt;(std::move(bound_args))</tt>.</ins>
<ins>
The behavior is undefined if
<tt>Bound</tt> is not <tt>unreachable_sentinel_t</tt>
and <tt><i>bound_</i></tt> is negative.</ins>
</p>
</blockquote>
</blockquote>
</li>
</ol>






<hr>
<h3><a name="3786" href="https://cplusplus.github.io/LWG/lwg-active.html#3786">3786</a>. Flat maps' deduction guide needs to default <tt>Allocator</tt> to be useful</h3>
<p><b>Section:</b> 24.6.9.2 <a href="https://wg21.link/flat.map.defn">[flat.map.defn]</a>, 24.6.10.2 <a href="https://wg21.link/flat.multimap.defn">[flat.multimap.defn]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Johel Ernesto Guerrero Pe&ntilde;a <b>Opened:</b> 2022-09-25 <b>Last modified:</b> 2023-02-09</p>
<p><b>Priority: </b>2
</p>
<p><b>Discussion:</b></p>
<p>
This originated from the editorial issue <a href="https://github.com/cplusplus/draft/issues/5800">#5800</a>.
<p/>
<a href="https://wg21.link/P0429R9">P0429R9</a> added some deduction guides with a non-defaulted <tt>Allocator</tt> 
template parameter and a corresponding function parameter that is defaulted. Since the 
template parameter <tt>Allocator</tt> is not defaulted, these deduction guides are never used.
</p>

<p><i>[2022-09-28; LWG telecon]</i></p>

<p>
We should not just ignore the allocator, it should be rebound and used for
the two container types.
</p>

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

<ol>

<li><p>Modify 24.6.9.2 <a href="https://wg21.link/flat.map.defn">[flat.map.defn]</a>, class template <tt>flat_map</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
template&lt;ranges::input_range R, class Compare = less&lt;<i>range-key-type</i>&lt;R&gt;&gt;,
         class Allocator <ins>= allocator&lt;void&gt;</ins>&gt;
  flat_map(from_range_t, R&amp;&amp;, Compare = Compare(), Allocator = Allocator())
    -&gt; flat_map&lt;<i>range-key-type</i>&lt;R&gt;, <i>range-mapped-type</i>&lt;R&gt;, Compare&gt;;
[&hellip;]
</pre>
</blockquote>
</li>

<li><p>Modify 24.6.10.2 <a href="https://wg21.link/flat.multimap.defn">[flat.multimap.defn]</a>, class template <tt>flat_multimap</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
template&lt;ranges::input_range R, class Compare = less&lt;<i>range-key-type</i>&lt;R&gt;&gt;,
         class Allocator <ins>= allocator&lt;void&gt;</ins>&gt;
  flat_multimap(from_range_t, R&amp;&amp;, Compare = Compare(), Allocator = Allocator())
    -&gt; flat_multimap&lt;<i>range-key-type</i>&lt;R&gt;, <i>range-mapped-type</i>&lt;R&gt;, Compare&gt;;
[&hellip;]
</pre>
</blockquote>
</li>
</ol>

</blockquote>

<p><i>[2022-10-19; Jonathan provides improved wording]</i></p>


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

<ol>
<li><p>Modify 24.6.1 <a href="https://wg21.link/container.adaptors.general">[container.adaptors.general]</a> as indicated:</p>

<blockquote>
<p>-8- The following exposition-only alias templates may appear in
deduction guides for container adaptors:
</p>
<blockquote><pre>
template&lt;class Container&gt;
  using <i>cont-key-type</i> =                                <i>// exposition only</i>
    remove_const_t&lt;typename Container::value_type::first_type&gt;;
template&lt;class Container&gt;
  using <i>cont-mapped-type</i> =                             <i>// exposition only</i>
    typename Container::value_type::second_type;
<ins>template&lt;class Allocator, class T&gt;
  using <i>alloc-rebind</i> =                             <i>// exposition only</i>
    typename allocator_traits&lt;Allocator&gt;::template rebind_alloc&lt;T&gt;;
</ins>
</pre></blockquote>
</blockquote>
</li>

<li><p>Modify 24.6.9.2 <a href="https://wg21.link/flat.map.defn">[flat.map.defn]</a>, class template <tt>flat_map</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
template&lt;ranges::input_range R, class Compare = less&lt;<i>range-key-type</i>&lt;R&gt;&gt;,
         class Allocator <ins>= allocator&lt;void&gt;</ins>&gt;
  flat_map(from_range_t, R&amp;&amp;, Compare = Compare(), Allocator = Allocator())
    -&gt; flat_map&lt;<i>range-key-type</i>&lt;R&gt;, <i>range-mapped-type</i>&lt;R&gt;, Compare<ins>,</ins>
         <ins>vector&lt;<i>range-key-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-key-type</i>&lt;R&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-mapped-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-mapped-type</i>&lt;R&gt;&gt;</ins>&gt;;

template&lt;ranges::input_range R, class Allocator&gt;
  flat_map(from_range_t, R&amp;&amp;, Allocator)
    -&gt; flat_map&lt;<i>range-key-type</i>&lt;R&gt;, <i>range-mapped-type</i>&lt;R&gt;<ins>, less&lt;<i>range-key-type</i>&lt;R&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-key-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-key-type</i>&lt;R&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-mapped-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-mapped-type</i>&lt;R&gt;&gt;</ins>&gt;;
[&hellip;]
</pre>
</blockquote>
</li>

<li><p>Modify 24.6.10.2 <a href="https://wg21.link/flat.multimap.defn">[flat.multimap.defn]</a>, class template <tt>flat_multimap</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
template&lt;ranges::input_range R, class Compare = less&lt;<i>range-key-type</i>&lt;R&gt;&gt;,
         class Allocator <ins>= allocator&lt;void&gt;</ins>&gt;
  flat_multimap(from_range_t, R&amp;&amp;, Compare = Compare(), Allocator = Allocator())
    -&gt; flat_multimap&lt;<i>range-key-type</i>&lt;R&gt;, <i>range-mapped-type</i>&lt;R&gt;, Compare<ins>,</ins>
         <ins>vector&lt;<i>range-key-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-key-type</i>&lt;R&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-mapped-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-mapped-type</i>&lt;R&gt;&gt;</ins>&gt;;

template&lt;ranges::input_range R, class Allocator&gt;
  flat_multimap(from_range_t, R&amp;&amp;, Allocator)
    -&gt; flat_multimap&lt;<i>range-key-type</i>&lt;R&gt;, <i>range-mapped-type</i>&lt;R&gt;<ins>, less&lt;<i>range-key-type</i>&lt;R&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-key-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-key-type</i>&lt;R&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-mapped-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-mapped-type</i>&lt;R&gt;&gt;</ins>&gt;;
[&hellip;]
</pre>
</blockquote>
</li>

<li><p>Modify 24.6.11.2 <a href="https://wg21.link/flat.set.defn">[flat.set.defn]</a>, class template <tt>flat_set</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
template&lt;ranges::input_range R, class Compare = less&lt;ranges::range_value_t&lt;R&gt;&gt;,
         class Allocator = allocator&lt;ranges::range_value_t&lt;R&gt;&gt;&gt;
  flat_set(from_range_t, R&amp;&amp;, Compare = Compare(), Allocator = Allocator())
    -&gt; flat_set&lt;ranges::range_value_t&lt;R&gt;, Compare<ins>,</ins>
         <ins>vector&lt;ranges::range_value_t&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, ranges::range_value_t&lt;R&gt;&gt;&gt;</ins>&gt;;

template&lt;ranges::input_range R, class Allocator&gt;
  flat_set(from_range_t, R&amp;&amp;, Allocator)
    -&gt; flat_set&lt;ranges::range_value_t&lt;R&gt;, less&lt;ranges::range_value_t&lt;R&gt;&gt;<ins>,</ins>
         <ins>vector&lt;ranges::range_value_t&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, ranges::range_value_t&lt;R&gt;&gt;&gt;</ins>&gt;;
[&hellip;]
</pre>
</blockquote>
</li>

<li><p>Modify 24.6.12.2 <a href="https://wg21.link/flat.multiset.defn">[flat.multiset.defn]</a>, class template <tt>flat_multiset</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
template&lt;ranges::input_range R, class Compare = less&lt;ranges::range_value_t&lt;R&gt;&gt;,
         class Allocator = allocator&lt;ranges::range_value_t&lt;R&gt;&gt;&gt;
  flat_multiset(from_range_t, R&amp;&amp;, Compare = Compare(), Allocator = Allocator())
    -&gt; flat_multiset&lt;ranges::range_value_t&lt;R&gt;, Compare<ins>,</ins>
         <ins>vector&lt;ranges::range_value_t&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, ranges::range_value_t&lt;R&gt;&gt;&gt;</ins>&gt;;

template&lt;ranges::input_range R, class Allocator&gt;
  flat_multiset(from_range_t, R&amp;&amp;, Allocator)
    -&gt; flat_multiset&lt;ranges::range_value_t&lt;R&gt;, less&lt;ranges::range_value_t&lt;R&gt;&gt;<ins>,</ins>
         <ins>vector&lt;ranges::range_value_t&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, ranges::range_value_t&lt;R&gt;&gt;&gt;</ins>&gt;;
[&hellip;]
</pre>
</blockquote>
</li>

</ol>

</blockquote>

<p><i>[2023-01-11; Jonathan Wakely provides improved wording]</i></p>

<p>
During LWG telecon Tim pointed out that because
<tt>allocator&lt;void&gt;</tt> does not meet the <i>Cpp17Allocator</i>
requirements, it might not "qualify as an allocator" and so would cause
the deduction guides to not participate in overload resolution, as per
24.6.1 <a href="https://wg21.link/container.adaptors.general">[container.adaptors.general]</a> p6 (6.4).
Use <tt>allocator&lt;byte&gt;</tt> instead.
</p>

<p><i>[Issaquah 2023-02-07; LWG]</i></p>

<p>
Edited proposed resolution to fix missing <ins><tt>&gt;</tt></ins>
in guides for maps.
Move to Immediate for C++23
</p>



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

<ol>
<li><p>Modify 24.6.1 <a href="https://wg21.link/container.adaptors.general">[container.adaptors.general]</a> as indicated:</p>

<blockquote>
<p><ins>-8- The following exposition-only alias template may appear in
deduction guides for container adaptors:</ins>
</p>
<blockquote><pre>
<ins>template&lt;class Allocator, class T&gt;
  using <i>alloc-rebind</i> =                                 <i>// exposition only</i>
    typename allocator_traits&lt;Allocator&gt;::template rebind_alloc&lt;T&gt;;
</ins>
</pre></blockquote>
</blockquote>
</li>

<li><p>Modify 24.6.9.2 <a href="https://wg21.link/flat.map.defn">[flat.map.defn]</a>, class template <tt>flat_map</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
template&lt;ranges::input_range R, class Compare = less&lt;<i>range-key-type</i>&lt;R&gt;&gt;,
         class Allocator <ins>= allocator&lt;byte&gt;</ins>&gt;
  flat_map(from_range_t, R&amp;&amp;, Compare = Compare(), Allocator = Allocator())
    -&gt; flat_map&lt;<i>range-key-type</i>&lt;R&gt;, <i>range-mapped-type</i>&lt;R&gt;, Compare<ins>,</ins>
         <ins>vector&lt;<i>range-key-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-key-type</i>&lt;R&gt;&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-mapped-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-mapped-type</i>&lt;R&gt;&gt;&gt;</ins>&gt;;

template&lt;ranges::input_range R, class Allocator&gt;
  flat_map(from_range_t, R&amp;&amp;, Allocator)
    -&gt; flat_map&lt;<i>range-key-type</i>&lt;R&gt;, <i>range-mapped-type</i>&lt;R&gt;<ins>, less&lt;<i>range-key-type</i>&lt;R&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-key-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-key-type</i>&lt;R&gt;&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-mapped-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-mapped-type</i>&lt;R&gt;&gt;&gt;</ins>&gt;;
[&hellip;]
</pre>
</blockquote>
</li>

<li><p>Modify 24.6.10.2 <a href="https://wg21.link/flat.multimap.defn">[flat.multimap.defn]</a>, class template <tt>flat_multimap</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
template&lt;ranges::input_range R, class Compare = less&lt;<i>range-key-type</i>&lt;R&gt;&gt;,
         class Allocator <ins>= allocator&lt;byte&gt;</ins>&gt;
  flat_multimap(from_range_t, R&amp;&amp;, Compare = Compare(), Allocator = Allocator())
    -&gt; flat_multimap&lt;<i>range-key-type</i>&lt;R&gt;, <i>range-mapped-type</i>&lt;R&gt;, Compare<ins>,</ins>
         <ins>vector&lt;<i>range-key-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-key-type</i>&lt;R&gt;&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-mapped-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-mapped-type</i>&lt;R&gt;&gt;&gt;</ins>&gt;;

template&lt;ranges::input_range R, class Allocator&gt;
  flat_multimap(from_range_t, R&amp;&amp;, Allocator)
    -&gt; flat_multimap&lt;<i>range-key-type</i>&lt;R&gt;, <i>range-mapped-type</i>&lt;R&gt;<ins>, less&lt;<i>range-key-type</i>&lt;R&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-key-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-key-type</i>&lt;R&gt;&gt;&gt;,</ins>
         <ins>vector&lt;<i>range-mapped-type</i>&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, <i>range-mapped-type</i>&lt;R&gt;&gt;&gt;</ins>&gt;;
[&hellip;]
</pre>
</blockquote>
</li>

<li><p>Modify 24.6.11.2 <a href="https://wg21.link/flat.set.defn">[flat.set.defn]</a>, class template <tt>flat_set</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
template&lt;ranges::input_range R, class Compare = less&lt;ranges::range_value_t&lt;R&gt;&gt;,
         class Allocator = allocator&lt;ranges::range_value_t&lt;R&gt;&gt;&gt;
  flat_set(from_range_t, R&amp;&amp;, Compare = Compare(), Allocator = Allocator())
    -&gt; flat_set&lt;ranges::range_value_t&lt;R&gt;, Compare<ins>,</ins>
         <ins>vector&lt;ranges::range_value_t&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, ranges::range_value_t&lt;R&gt;&gt;&gt;</ins>&gt;;

template&lt;ranges::input_range R, class Allocator&gt;
  flat_set(from_range_t, R&amp;&amp;, Allocator)
    -&gt; flat_set&lt;ranges::range_value_t&lt;R&gt;, less&lt;ranges::range_value_t&lt;R&gt;&gt;<ins>,</ins>
         <ins>vector&lt;ranges::range_value_t&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, ranges::range_value_t&lt;R&gt;&gt;&gt;</ins>&gt;;
[&hellip;]
</pre>
</blockquote>
</li>

<li><p>Modify 24.6.12.2 <a href="https://wg21.link/flat.multiset.defn">[flat.multiset.defn]</a>, class template <tt>flat_multiset</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
template&lt;ranges::input_range R, class Compare = less&lt;ranges::range_value_t&lt;R&gt;&gt;,
         class Allocator = allocator&lt;ranges::range_value_t&lt;R&gt;&gt;&gt;
  flat_multiset(from_range_t, R&amp;&amp;, Compare = Compare(), Allocator = Allocator())
    -&gt; flat_multiset&lt;ranges::range_value_t&lt;R&gt;, Compare<ins>,</ins>
         <ins>vector&lt;ranges::range_value_t&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, ranges::range_value_t&lt;R&gt;&gt;&gt;</ins>&gt;;

template&lt;ranges::input_range R, class Allocator&gt;
  flat_multiset(from_range_t, R&amp;&amp;, Allocator)
    -&gt; flat_multiset&lt;ranges::range_value_t&lt;R&gt;, less&lt;ranges::range_value_t&lt;R&gt;&gt;<ins>,</ins>
         <ins>vector&lt;ranges::range_value_t&lt;R&gt;, <i>alloc-rebind</i>&lt;Allocator, ranges::range_value_t&lt;R&gt;&gt;&gt;</ins>&gt;;
[&hellip;]
</pre>
</blockquote>
</li>

</ol>






<hr>
<h3><a name="3803" href="https://cplusplus.github.io/LWG/lwg-active.html#3803">3803</a>. <tt>flat_<i>foo</i></tt> constructors taking <tt>KeyContainer</tt> lack <tt>KeyCompare</tt> parameter</h3>
<p><b>Section:</b> 24.6.9 <a href="https://wg21.link/flat.map">[flat.map]</a>, 24.6.10 <a href="https://wg21.link/flat.multimap">[flat.multimap]</a>, 24.6.11 <a href="https://wg21.link/flat.set">[flat.set]</a>, 24.6.12 <a href="https://wg21.link/flat.multiset">[flat.multiset]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Arthur O'Dwyer <b>Opened:</b> 2022-10-25 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>1
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#flat.map">active issues</a> in [flat.map].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#flat.map">issues</a> in [flat.map].</p>
<p><b>Discussion:</b></p>
<p>
<tt>flat_set</tt>'s current constructor overload set has these two overloads:
</p>
<blockquote><pre>
explicit flat_set(container_type cont);
template&lt;class Allocator&gt;
  flat_set(const container_type&amp; cont, const Allocator&amp; a);
</pre></blockquote>
<p>
I believe it should have these two in addition:
</p>
<blockquote><pre>
flat_set(const key_compare&amp; comp, container_type cont);
template&lt;class Allocator&gt;
  flat_set(const key_compare&amp; comp, const container_type&amp; cont, const Allocator&amp; a);
</pre></blockquote>
<p>
with corresponding deduction guides. Similar wording changes would have to be made to all the 
<tt>flat_<i>foo</i></tt> containers.
<p/>
Tony Table:
</p>
<blockquote><pre>
struct LessWhenDividedBy {
  int divisor_;
  bool operator()(int x, int y) const { return x/divisor_ &lt; y/divisor_; }
};
std::flat_set&lt;int, LessWhenDividedBy&gt; s(data.begin(), data.end(), LessWhenDividedBy(10));
// BEFORE AND AFTER: okay, but cumbersome
std::flat_set&lt;int, LessWhenDividedBy&gt; s(data);
// BEFORE AND AFTER: oops, this default-constructs the comparator

std::flat_set&lt;int, LessWhenDividedBy&gt; s(LessWhenDividedBy(10), data);
// BEFORE: fails to compile
// AFTER: compiles successfully
</pre></blockquote>

<p><i>[2022-11-04; Reflector poll]</i></p>

<p>
Set priority to 1 after reflector poll.
</p>

<p><i>[2023-02-09 Tim adds wording]</i></p>

<p>
For each construction that takes containers, this wording allow a comparator to be specified as well.
Differing from the suggestion in the issue, the comparator goes last (but before the allocator),
for consistency with every other constructor of <tt>flat_<i>meow</i></tt> taking a comparator.
(This is inconsistent with <tt>priority_queue</tt>, but consistency among the type's own
constructors seems more important.)
</p>

<p><i>[Issaquah 2023-02-09; LWG]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>
<li><p>Add a new bullet to 24.6.1 <a href="https://wg21.link/container.adaptors.general">[container.adaptors.general]</a> p6 as indicated:</p>
<blockquote>
<p> -6- A deduction guide for a container adaptor shall not participate in overload 
resolution if any of the following are true:</p>
<ol style="list-style-type:none">
<li>
<p><ins>&mdash; (6.?) It has both <tt>KeyContainer</tt> and <tt>Compare</tt>
template parameters, and <tt>is_invocable_v&lt;const Compare&amp;, 
const typename KeyContainer::value_type&amp;, 
const typename KeyContainer::value_type&amp;&gt;</tt> is not a valid expression
or is <tt>false</tt>.</ins>
</p>
</li>
</ol>
</blockquote>
</li>
<li><p>Modify 24.6.9.2 <a href="https://wg21.link/flat.map.defn">[flat.map.defn]</a> as indicated:</p>
<blockquote>
<pre>
namespace std {
  template&lt;class Key, class T, class Compare = less&lt;Key&gt;,
           class KeyContainer = vector&lt;Key&gt;, class MappedContainer = vector&lt;T&gt;&gt;
  class flat_map {
  public:
    [&hellip;]
    // 24.6.9.3 <a href="https://wg21.link/flat.map.cons">[flat.map.cons]</a>, construct/copy/destroy
    flat_map() : flat_map(key_compare()) { }

    flat_map(key_container_type key_cont, mapped_container_type mapped_cont<ins>,
             const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_map(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
               const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_map(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
               const key_compare&amp; comp, const Allocator&amp; a);</ins>

    flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont<ins>,
             const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_map(sorted_unique_t, const key_container_type&amp; key_cont,
               const mapped_container_type&amp; mapped_cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_map(sorted_unique_t, const key_container_type&amp; key_cont,
               const mapped_container_type&amp; mapped_cont, 
               const key_compare&amp; comp, const Allocator&amp; a);</ins>
    [&hellip;]
  };

  template&lt;class KeyContainer, class MappedContainer<ins>, class Compare = less&lt;typename KeyContainer::value_type&gt;</ins>&gt;
    flat_map(KeyContainer, MappedContainer<ins>, Compare = Compare()</ins>)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  <ins>Compare</ins><del>less&lt;typename KeyContainer::value_type&gt;</del>, KeyContainer, MappedContainer&gt;;

  template&lt;class KeyContainer, class MappedContainer, class Allocator&gt;
    flat_map(KeyContainer, MappedContainer, Allocator)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  less&lt;typename KeyContainer::value_type&gt;, KeyContainer, MappedContainer&gt;;
<ins>  template&lt;class KeyContainer, class MappedContainer, class Compare, class Allocator&gt;
    flat_map(KeyContainer, MappedContainer, Compare, Allocator)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, KeyContainer, MappedContainer&gt;;</ins>


  template&lt;class KeyContainer, class MappedContainer<ins>, class Compare = less&lt;typename KeyContainer::value_type&gt;</ins>&gt;
    flat_map(sorted_unique_t, KeyContainer, MappedContainer<ins>, Compare = Compare()</ins>)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  <ins>Compare</ins><del>less&lt;typename KeyContainer::value_type&gt;</del>, KeyContainer, MappedContainer&gt;;

  template&lt;class KeyContainer, class MappedContainer, class Allocator&gt;
    flat_map(sorted_unique_t, KeyContainer, MappedContainer, Allocator)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  less&lt;typename KeyContainer::value_type&gt;, KeyContainer, MappedContainer&gt;;
<ins>  template&lt;class KeyContainer, class MappedContainer, class Compare, class Allocator&gt;
    flat_map(sorted_unique_t, KeyContainer, MappedContainer, Compare, Allocator)
      -&gt; flat_map&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, KeyContainer, MappedContainer&gt;;</ins>
  [&hellip;]
}
</pre>
</blockquote>
</li>
<li><p>Modify 24.6.9.3 <a href="https://wg21.link/flat.map.cons">[flat.map.cons]</a> as indicated:</p>
<blockquote>
<pre>
flat_map(key_container_type key_cont, mapped_container_type mapped_cont<ins>,
         const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> Initializes <tt>c.keys</tt> with <tt>std::move(key_cont)</tt><ins>,</ins>
<del>and</del> <tt>c.values</tt> with <tt>std::move(mapped_cont)</tt><ins>, and <tt>compare</tt> with <tt>comp</tt></ins>
<del>; value-initializes <tt>compare</tt></del>; sorts the range <tt>[begin(), end())</tt>
with respect to <tt>value_comp()</tt>; and finally erases the duplicate elements as if by:
</p>
<blockquote>
<pre>
auto zv = ranges::zip_view(c.keys, c.values);
auto it = ranges::unique(zv, key_equiv(compare)).begin();
auto dist = distance(zv.begin(), it);
c.keys.erase(c.keys.begin() + dist, c.keys.end());
c.values.erase(c.values.begin() + dist, c.values.end());
</pre>
</blockquote>
<p>
-2- <i>Complexity:</i> Linear in <i>N</i> if the container arguments are already 
sorted with respect to <tt>value_comp()</tt> and otherwise <i>N</i> log <i>N</i>,
where <i>N</i> is the value of <tt>key_cont.size()</tt> before this call.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_map(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
           const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_map(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
           const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> <tt>uses_allocator_v&lt;key_container_type, Allocator&gt;</tt> is <tt>true</tt>
and <tt>uses_allocator_v&lt;mapped_container_type, Allocator&gt;</tt> is <tt>true</tt>.
<p/>
-4- <i>Effects:</i> Equivalent to <tt>flat_map(key_cont, mapped_cont)</tt>
<ins>and <tt>flat_map(key_cont, mapped_cont, comp)</tt>, respectively</ins>, 
except that <tt>c.keys</tt> and <tt>c.values</tt> are constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-5- <i>Complexity:</i> Same as <tt>flat_map(key_cont, mapped_cont)</tt>
<ins>and <tt>flat_map(key_cont, mapped_cont, comp)</tt>, respectively</ins>.
</p>
</blockquote>

<pre>
flat_map(sorted_unique_t, key_container_type key_cont, mapped_container_type mapped_cont<ins>,
         const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-6- <i>Effects:</i> Initializes <tt>c.keys</tt> with <tt>std::move(key_cont)</tt><ins>,</ins>
<del>and</del> <tt>c.values</tt> with <tt>std::move(mapped_cont)</tt><ins>, and <tt>compare</tt> with <tt>comp</tt></ins>
<del>; value-initializes <tt>compare</tt></del>.
<p/>
-7- <i>Complexity:</i> Constant.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_map(sorted_unique_t s, const key_container_type&amp; key_cont,
           const mapped_container_type&amp; mapped_cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_map(sorted_unique_t s, const key_container_type&amp; key_cont, 
           const mapped_container_type&amp; mapped_cont, const key_compare&amp; comp,
           const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-8- <i>Constraints:</i> <tt>uses_allocator_v&lt;key_container_type, Allocator&gt;</tt> is <tt>true</tt>
and <tt>uses_allocator_v&lt;mapped_container_type, Allocator&gt;</tt> is <tt>true</tt>.
<p/>
-9- <i>Effects:</i> Equivalent to <tt>flat_map(s, key_cont, mapped_cont)</tt>
<ins>and <tt>flat_map(s, key_cont, mapped_cont, comp)</tt>, respectively</ins>, 
except that <tt>c.keys</tt> and <tt>c.values</tt> are constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-10- <i>Complexity:</i> Linear.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 24.6.10.2 <a href="https://wg21.link/flat.multimap.defn">[flat.multimap.defn]</a> as indicated:</p>
<blockquote>
<pre>
namespace std {
  template&lt;class Key, class T, class Compare = less&lt;Key&gt;,
           class KeyContainer = vector&lt;Key&gt;, class MappedContainer = vector&lt;T&gt;&gt;
  class flat_multimap {
  public:
    [&hellip;]
    // 24.6.10.3 <a href="https://wg21.link/flat.multimap.cons">[flat.multimap.cons]</a>, construct/copy/destroy
    flat_multimap() : flat_multimap(key_compare()) { }

    flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont<ins>,
                  const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_multimap(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
                    const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_multimap(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
                    const key_compare&amp; comp, const Allocator&amp; a);</ins>

    flat_multimap(sorted_equivalent_t, 
                  key_container_type key_cont, mapped_container_type mapped_cont<ins>,
                  const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_multimap(sorted_equivalent_t, const key_container_type&amp; key_cont,
                    const mapped_container_type&amp; mapped_cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_multimap(sorted_equivalent_t, const key_container_type&amp; key_cont,
                    const mapped_container_type&amp; mapped_cont, 
                    const key_compare&amp; comp, const Allocator&amp; a);</ins>
    [&hellip;]
  };

  template&lt;class KeyContainer, class MappedContainer<ins>, class Compare = less&lt;typename KeyContainer::value_type&gt;</ins>&gt;
    flat_multimap(KeyContainer, MappedContainer<ins>, Compare = Compare()</ins>)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  <ins>Compare</ins><del>less&lt;typename KeyContainer::value_type&gt;</del>, KeyContainer, MappedContainer&gt;;

  template&lt;class KeyContainer, class MappedContainer, class Allocator&gt;
    flat_multimap(KeyContainer, MappedContainer, Allocator)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  less&lt;typename KeyContainer::value_type&gt;, KeyContainer, MappedContainer&gt;;
<ins>  template&lt;class KeyContainer, class MappedContainer, class Compare, class Allocator&gt;
    flat_multimap(KeyContainer, MappedContainer, Compare, Allocator)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, KeyContainer, MappedContainer&gt;;</ins>


  template&lt;class KeyContainer, class MappedContainer<ins>, class Compare = less&lt;typename KeyContainer::value_type&gt;</ins>&gt;
    flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer<ins>, Compare = Compare()</ins>)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  <ins>Compare</ins><del>less&lt;typename KeyContainer::value_type&gt;</del>, KeyContainer, MappedContainer&gt;;

  template&lt;class KeyContainer, class MappedContainer, class Allocator&gt;
    flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Allocator)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  less&lt;typename KeyContainer::value_type&gt;, KeyContainer, MappedContainer&gt;;
<ins>  template&lt;class KeyContainer, class MappedContainer, class Compare, class Allocator&gt;
    flat_multimap(sorted_equivalent_t, KeyContainer, MappedContainer, Compare, Allocator)
      -&gt; flat_multimap&lt;typename KeyContainer::value_type, typename MappedContainer::value_type,
                  Compare, KeyContainer, MappedContainer&gt;;</ins>
  [&hellip;]
}
</pre>
</blockquote>
</li>
<li><p>Modify 24.6.10.3 <a href="https://wg21.link/flat.multimap.cons">[flat.multimap.cons]</a> as indicated:</p>
<blockquote>
<pre>
flat_multimap(key_container_type key_cont, mapped_container_type mapped_cont<ins>,
              const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> Initializes <tt>c.keys</tt> with <tt>std::move(key_cont)</tt><ins>,</ins>
<del>and</del> <tt>c.values</tt> with <tt>std::move(mapped_cont)</tt><ins>, and <tt>compare</tt> with <tt>comp</tt></ins>
<del>; value-initializes <tt>compare</tt></del>; and sorts the range <tt>[begin(), end())</tt>
with respect to <tt>value_comp()</tt>.
</p>
<p>
-2- <i>Complexity:</i> Linear in <i>N</i> if the container arguments are already 
sorted with respect to <tt>value_comp()</tt> and otherwise <i>N</i> log <i>N</i>,
where <i>N</i> is the value of <tt>key_cont.size()</tt> before this call.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_multimap(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
                const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_multimap(const key_container_type&amp; key_cont, const mapped_container_type&amp; mapped_cont,
                const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> <tt>uses_allocator_v&lt;key_container_type, Allocator&gt;</tt> is <tt>true</tt>
and <tt>uses_allocator_v&lt;mapped_container_type, Allocator&gt;</tt> is <tt>true</tt>.
<p/>
-4- <i>Effects:</i> Equivalent to <tt>flat_multimap(key_cont, mapped_cont)</tt>
<ins>and <tt>flat_multimap(key_cont, mapped_cont, comp)</tt>, respectively</ins>, 
except that <tt>c.keys</tt> and <tt>c.values</tt> are constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-5- <i>Complexity:</i> Same as <tt>flat_multimap(key_cont, mapped_cont)</tt>
<ins>and <tt>flat_multimap(key_cont, mapped_cont, comp)</tt>, respectively</ins>.
</p>
</blockquote>

<pre>
flat_multimap(sorted_equivalent_t, key_container_type key_cont, mapped_container_type mapped_cont<ins>,
              const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-6- <i>Effects:</i> Initializes <tt>c.keys</tt> with <tt>std::move(key_cont)</tt><ins>,</ins>
<del>and</del> <tt>c.values</tt> with <tt>std::move(mapped_cont)</tt><ins>, and <tt>compare</tt> with <tt>comp</tt></ins>
<del>; value-initializes <tt>compare</tt></del>.
<p/>
-7- <i>Complexity:</i> Constant.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_multimap(sorted_equivalent_t s, const key_container_type&amp; key_cont,
               const mapped_container_type&amp; mapped_cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_multimap(sorted_equivalent_t s, const key_container_type&amp; key_cont, 
                const mapped_container_type&amp; mapped_cont, const key_compare&amp; comp,
                const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-8- <i>Constraints:</i> <tt>uses_allocator_v&lt;key_container_type, Allocator&gt;</tt> is <tt>true</tt>
and <tt>uses_allocator_v&lt;mapped_container_type, Allocator&gt;</tt> is <tt>true</tt>.
<p/>
-9- <i>Effects:</i> Equivalent to <tt>flat_multimap(s, key_cont, mapped_cont)</tt>
<ins>and <tt>flat_multimap(s, key_cont, mapped_cont, comp)</tt>, respectively</ins>, 
except that <tt>c.keys</tt> and <tt>c.values</tt> are constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-10- <i>Complexity:</i> Linear.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 24.6.11.2 <a href="https://wg21.link/flat.set.defn">[flat.set.defn]</a> as indicated:</p>
<blockquote>
<pre>
namespace std {
  template&lt;class Key, class Compare = less&lt;Key&gt;, class KeyContainer = vector&lt;Key&gt;&gt;
  class flat_set {
  public:
    [&hellip;]

    // [flat.set.cons], constructors
    flat_set() : flat_set(key_compare()) { }

    explicit flat_set(container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_set(const container_type&amp; cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_set(const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>

    flat_set(sorted_unique_t, container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>)
      : <i>c</i>(std::move(cont)), <i>compare</i>(<ins>comp</ins><del>key_compare()</del>) { }
    template&lt;class Allocator&gt;
      flat_set(sorted_unique_t, const container_type&amp; cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_set(sorted_unique_t, const container_type&amp; cont, 
               const key_compare&amp; comp, const Allocator&amp; a);</ins>

    [&hellip;]
  };

<ins>
  template&lt;class KeyContainer, class Compare = less&lt;typename KeyContainer::value_type&gt;&gt;
    flat_set(KeyContainer, Compare = Compare())
      -&gt; flat_set&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
  template&lt;class KeyContainer, class Allocator&gt;
    flat_set(KeyContainer, Allocator)
      -&gt; flat_set&lt;typename KeyContainer::value_type, less&lt;typename KeyContainer::value_type&gt;, KeyContainer&gt;;
  template&lt;class KeyContainer, class Compare, class Allocator&gt;
    flat_set(KeyContainer, Compare, Allocator)
      -&gt; flat_set&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;

  template&lt;class KeyContainer, class Compare = less&lt;typename KeyContainer::value_type&gt;&gt;
    flat_set(sorted_unique_t, KeyContainer, Compare = Compare())
      -&gt; flat_set&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
  template&lt;class KeyContainer, class Allocator&gt;
    flat_set(sorted_unique_t, KeyContainer, Allocator)
      -&gt; flat_set&lt;typename KeyContainer::value_type, less&lt;typename KeyContainer::value_type&gt;, KeyContainer&gt;;
  template&lt;class KeyContainer, class Compare, class Allocator&gt;
    flat_set(sorted_unique_t, KeyContainer, Compare, Allocator)
      -&gt; flat_set&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
</ins>
  [&hellip;]
}
</pre>
</blockquote>
</li>
<li><p>Modify 24.6.11.3 <a href="https://wg21.link/flat.set.cons">[flat.set.cons]</a> as indicated:</p>
<blockquote>
<pre>
flat_set(container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> Initializes <tt><i>c</i></tt> with <tt>std::move(cont)</tt>
<ins> and <tt><i>compare</i></tt> with <tt>comp</tt></ins>
<del>, value-initializes <tt><i>compare</i></tt></del>, sorts the range <tt>[begin(), end())</tt>
with respect to <tt><i>compare</i></tt>, and finally erases all but the first element from each group 
of consecutive equivalent elements.
</p>
<p>
-2- <i>Complexity:</i> Linear in <i>N</i> if <tt>cont</tt> is already 
sorted with respect to <tt><i>compare</i></tt> and otherwise <i>N</i> log <i>N</i>,
where <i>N</i> is the value of <tt>cont.size()</tt> before this call.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_set(const container_type&amp; cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_set(const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> <tt>uses_allocator_v&lt;container_type, Allocator&gt;</tt> is <tt>true</tt>.
<p/>
-4- <i>Effects:</i> Equivalent to <tt>flat_set(cont)</tt>
<ins>and <tt>flat_set(cont, comp)</tt>, respectively</ins>, 
except that <tt><i>c</i></tt> is constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-5- <i>Complexity:</i> Same as <tt>flat_set(cont)</tt>
<ins>and <tt>flat_set(cont, comp)</tt>, respectively</ins>.
</p>
</blockquote>

<pre>
template&lt;class Allocator&gt;
  flat_set(sorted_unique_t s, const container_type&amp; cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_set(sorted_unique_t s, const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-6- <i>Constraints:</i> <tt>uses_allocator_v&lt;container_type, Allocator&gt;</tt> is <tt>true</tt>.
<p/>
-7- <i>Effects:</i> Equivalent to <tt>flat_set(s, cont)</tt>
<ins>and <tt>flat_set(s, cont, comp)</tt>, respectively</ins>, 
except that <tt><i>c</i></tt> is constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-8- <i>Complexity:</i> Linear.
</p>
</blockquote>
</blockquote>
</li>
<li><p>Modify 24.6.12.2 <a href="https://wg21.link/flat.multiset.defn">[flat.multiset.defn]</a> as indicated:</p>
<blockquote>
<pre>
namespace std {
  template&lt;class Key, class Compare = less&lt;Key&gt;, class KeyContainer = vector&lt;Key&gt;&gt;
  class flat_multiset {
  public:
    [&hellip;]

    // [flat.multiset.cons], constructors
    flat_multiset() : flat_multiset(key_compare()) { }

    explicit flat_multiset(container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>);
    template&lt;class Allocator&gt;
      flat_multiset(const container_type&amp; cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_multiset(const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>

    flat_multiset(sorted_equivalent_t, container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>)
      : <i>c</i>(std::move(cont)), <i>compare</i>(<ins>comp</ins><del>key_compare()</del>) { }
    template&lt;class Allocator&gt;
      flat_multiset(sorted_equivalent_t, const container_type&amp; cont, const Allocator&amp; a);
<ins>    template&lt;class Allocator&gt;
      flat_multiset(sorted_equivalent_t, const container_type&amp; cont, 
                    const key_compare&amp; comp, const Allocator&amp; a);</ins>

    [&hellip;]
  };

<ins>
  template&lt;class KeyContainer, class Compare = less&lt;typename KeyContainer::value_type&gt;&gt;
    flat_multiset(KeyContainer, Compare = Compare())
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
  template&lt;class KeyContainer, class Allocator&gt;
    flat_multiset(KeyContainer, Allocator)
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, less&lt;typename KeyContainer::value_type&gt;, KeyContainer&gt;;
  template&lt;class KeyContainer, class Compare, class Allocator&gt;
    flat_multiset(KeyContainer, Compare, Allocator)
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;

  template&lt;class KeyContainer, class Compare = less&lt;typename KeyContainer::value_type&gt;&gt;
    flat_multiset(sorted_equivalent_t, KeyContainer, Compare = Compare())
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
  template&lt;class KeyContainer, class Allocator&gt;
    flat_multiset(sorted_equivalent_t, KeyContainer, Allocator)
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, less&lt;typename KeyContainer::value_type&gt;, KeyContainer&gt;;
  template&lt;class KeyContainer, class Compare, class Allocator&gt;
    flat_multiset(sorted_equivalent_t, KeyContainer, Compare, Allocator)
      -&gt; flat_multiset&lt;typename KeyContainer::value_type, Compare, KeyContainer&gt;;
</ins>
  [&hellip;]
}
</pre>
</blockquote>
</li>
<li><p>Modify 24.6.12.3 <a href="https://wg21.link/flat.multiset.cons">[flat.multiset.cons]</a> as indicated:</p>
<blockquote>
<pre>
flat_multiset(container_type cont<ins>, const key_compare&amp; comp = key_compare()</ins>);
</pre>
<blockquote>
<p>
-1- <i>Effects:</i> Initializes <tt><i>c</i></tt> with <tt>std::move(cont)</tt>
<ins> and <tt><i>compare</i></tt> with <tt>comp</tt></ins>
<del>, value-initializes <tt><i>compare</i></tt></del>, and sorts the range <tt>[begin(), end())</tt>
with respect to <tt><i>compare</i></tt>.
</p>
<p>
-2- <i>Complexity:</i> Linear in <i>N</i> if <tt>cont</tt> is already 
sorted with respect to <tt><i>compare</i></tt> and otherwise <i>N</i> log <i>N</i>,
where <i>N</i> is the value of <tt>cont.size()</tt> before this call.
</p>
</blockquote>
<pre>
template&lt;class Allocator&gt;
  flat_multiset(const container_type&amp; cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_multiset(const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> <tt>uses_allocator_v&lt;container_type, Allocator&gt;</tt> is <tt>true</tt>.
<p/>
-4- <i>Effects:</i> Equivalent to <tt>flat_multiset(cont)</tt>
<ins>and <tt>flat_multiset(cont, comp)</tt>, respectively</ins>, 
except that <tt><i>c</i></tt> is constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-5- <i>Complexity:</i> Same as <tt>flat_multiset(cont)</tt>
<ins>and <tt>flat_multiset(cont, comp)</tt>, respectively</ins>.
</p>
</blockquote>

<pre>
template&lt;class Allocator&gt;
  flat_multiset(sorted_equivalent_t s, const container_type&amp; cont, const Allocator&amp; a);
<ins>template&lt;class Allocator&gt;
  flat_multiset(sorted_equivalent_t s, const container_type&amp; cont, const key_compare&amp; comp, const Allocator&amp; a);</ins>
</pre>
<blockquote>
<p>
-6- <i>Constraints:</i> <tt>uses_allocator_v&lt;container_type, Allocator&gt;</tt> is <tt>true</tt>.
<p/>
-7- <i>Effects:</i> Equivalent to <tt>flat_multiset(s, cont)</tt>
<ins>and <tt>flat_multiset(s, cont, comp)</tt>, respectively</ins>, 
except that <tt><i>c</i></tt> is constructed with 
uses-allocator construction (20.2.8.2 <a href="https://wg21.link/allocator.uses.construction">[allocator.uses.construction]</a>).
<p/>
-8- <i>Complexity:</i> Linear.
</p>
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3810" href="https://cplusplus.github.io/LWG/lwg-active.html#3810">3810</a>. CTAD for <tt>std::basic_format_args</tt></h3>
<p><b>Section:</b> 22.14.8.3 <a href="https://wg21.link/format.args">[format.args]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Jonathan Wakely <b>Opened:</b> 2022-11-03 <b>Last modified:</b> 2023-02-07</p>
<p><b>Priority: </b>3
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#format.args">issues</a> in [format.args].</p>
<p><b>Discussion:</b></p>
<p>
It seems desirable for this should work:
</p>
<blockquote><pre>
auto args_store = std::make_format_args&lt;C&gt;(1,2,3);
// &hellip;
std::basic_format_args args = args_store;
</pre></blockquote>
<p>
i.e. CTAD should deduce the <tt>Context</tt> argument from the <tt><i>fmt-store-args</i>&lt;C, int, int, int&gt;</tt> 
object returned by <tt>make_format_args</tt>.
<p/>
Another example (from Tomasz Kami&nacute;ski):
<p/>
Given:
</p>
<blockquote><pre>
template&lt;typename Context&gt;
void foo(basic_format_args&lt;Context&gt; c);

foo(make_format_args&lt;SomeContext&gt;(&hellip;)); // won't work
foo(basic_format_args(make_format_args&lt;SomeContext&gt;(&hellip;))); // should work
</pre></blockquote>
<p>
Since <tt><i>fmt-store-args</i></tt> is exposition-only, it's not entirely clear that it must have 
exactly the form shown in 22.14.8.2 <a href="https://wg21.link/format.arg.store">[format.arg.store]</a>. E.g. maybe it can have different template arguments, 
or could be a nested type defined inside <tt>basic_format_args</tt>. I don't know how much of the exposition-only 
spec is actually required for conformance. If CTAD is already intended to be required, it's a bit subtle.
<p/>
If we want the CTAD to work (and I think it's nice if it does) we could make that explicit by adding a deduction guide.
</p>

<p><i>[Kona 2022-11-12; Set priority to 3, status to LEWG]</i></p>


<p><i>[2023-01-10; LEWG telecon]</i></p>

<p>Unanimous consensus in favor.</p>

<p><i>[Issaquah 2023-02-06; LWG]</i></p>

<p>Unanimous consent (9/0/0) to move to Immediate for C++23.</p>



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

<ol>
<li><p>Modify 22.14.8.3 <a href="https://wg21.link/format.args">[format.args]</a> as indicated:</p>

<blockquote>
<pre>
namespace std {
  template&lt;class Context&gt;
  class basic_format_args {
    size_t size_;                           <i>// exposition only</i>
    const basic_format_arg&lt;Context&gt;* data_; <i>// exposition only</i>

  public:
    basic_format_args() noexcept;

    template&lt;class... Args&gt;
      basic_format_args(const <i>format-arg-store</i>&lt;Context, Args...&gt;&amp; store) noexcept;

    basic_format_arg&lt;Context&gt; get(size_t i) const noexcept;
  };
  
  <ins>template&lt;class Context, class... Args&gt;
    basic_format_args(<i>format-arg-store</i>&lt;Context, Args...&gt;) -&gt; basic_format_args&lt;Context&gt;;</ins>
}
</pre>
</blockquote>
</li>

</ol>





<hr>
<h3><a name="3827" href="https://cplusplus.github.io/LWG/lwg-active.html#3827">3827</a>. Deprecate <tt>&lt;stdalign.h&gt;</tt> and <tt>&lt;stdbool.h&gt;</tt> macros</h3>
<p><b>Section:</b> 17.14.4 <a href="https://wg21.link/stdalign.h.syn">[stdalign.h.syn]</a>, 17.14.5 <a href="https://wg21.link/stdbool.h.syn">[stdbool.h.syn]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> GB <b>Opened:</b> 2022-11-10 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
This is the resolution for NB comments:
<ul>
<li><b><a href="https://github.com/cplusplus/nbballot/issues/454">GB-081</a></b> 17.14.4 [stdalign.h.syn] Deprecate contents of &lt;stdalign.h&gt;.
</li>
<li><b><a href="https://github.com/cplusplus/nbballot/issues/453">GB-082</a></b> 17.14.5 [stdbool.h.syn] Deprecate contents of &lt;stdbool.h&gt;.
</li>
</ul>
</p>

<p><b>GB-081:</b></p>
<p>
C2x defines <tt>alignas</tt> as a keyword, so <tt>&lt;stdalign.h&gt;</tt> is empty in C2x. C++23 should 
deprecate the <tt>__alignas_is_defined</tt> macro now, rather than wait until a future C++ standard is based on C2x. 
That gives users longer to prepare for the removal of the macro.
</p>
<p>Recommended change:
Deprecate <tt>__alignas_is_defined</tt> and move it to Annex D.
Maybe keep a note in 17.14.4 <a href="https://wg21.link/stdalign.h.syn">[stdalign.h.syn]</a>
that the macro is present but deprecated.
</p>

<p><b>GB-082:</b></p>
<p>
C2x supports <tt>bool</tt> as a built-in type, and <tt>true</tt> and <tt>false</tt> as keywords. 
Consequently, C2x marks the <tt>__bool_true_false_are_defined</tt> as obsolescent. C++23 should 
deprecate that attribute now, rather than wait until a future C++ standard is based on C2x. That 
gives users longer to prepare for the removal of the macro.
</p>
<p>Recommended change:
Deprecate <tt>__bool_true_false_are_defined</tt> and move it to Annex D.
Maybe keep a note in 17.14.5 <a href="https://wg21.link/stdbool.h.syn">[stdbool.h.syn]</a> that the macro is present but deprecated.
</p>

<p><i>[Kona 2022-11-10; Jonathan provides wording]</i></p>

<p><i>[Kona 2022-11-10; Waiting for LEWG electronic polling]</i></p>


<p><i>[2022-11-08; Kona LEWG]</i></p>

<p>Strong consensus to accept GB-81. Strong consensus to accept GB-82.</p>

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

<ol>
<li><p>Modify 17.14.4 <a href="https://wg21.link/stdalign.h.syn">[stdalign.h.syn]</a> as indicated:</p>

<blockquote>
<p><b>17.14.4 Header <tt>&lt;stdalign.h&gt;</tt> synopsis [stdalign.h.syn]</b></p>

<blockquote><pre>
<del>#define __alignas_is_defined 1</del>
</pre></blockquote>
<p>-1- The contents of the C++ header <tt>&lt;stdalign.h&gt;</tt> are the same
as the C standard library header <tt>&lt;stdalign.h&gt;</tt>, with the
following changes:
The header <tt>&lt;stdalign.h&gt;</tt> does not define
a macro named <tt>alignas</tt>.
<ins>
The macro <tt>__alignas_is_defined</tt> ( [depr.c.macros]) is deprecated.
</ins>
</p>
<p><span style="font-variant: small-caps">See also</span>: ISO C 7.15</p>
</blockquote>

</li>

<li><p>Modify 17.14.5 <a href="https://wg21.link/stdbool.h.syn">[stdbool.h.syn]</a> as indicated:</p>

<blockquote>
<p><b>17.14.5 Header <tt>&lt;stdbool.h&gt;</tt> synopsis [stdbool.h.syn]</b></p>

<blockquote><pre>
<del>#define __bool_true_false_are_defined 1</del>
</pre></blockquote>
<p>-1- The contents of the C++ header <tt>&lt;stdbool.h&gt;</tt> are the same
as the C standard library header <tt>&lt;stdbool.h&gt;</tt>, with the
following changes:
The header <tt>&lt;stdbool.h&gt;</tt> does not define
macros named <tt>bool</tt>, <tt>true</tt>, or <tt>false</tt>.
<ins>
The macro <tt>__bool_true_false_are_defined</tt>
( [depr.c.macros]) is deprecated.
</ins>
</p>
<p><span style="font-variant: small-caps">See also</span>: ISO C 7.18</p>
</blockquote>
</li>

<li>Add a new subclause to Annex D <a href="https://wg21.link/depr">[depr]</a> between
D.10 <a href="https://wg21.link/depr.res.on.required">[depr.res.on.required]</a> and
D.11 <a href="https://wg21.link/depr.relops">[depr.relops]</a>, with this content:

<blockquote>
<ins>
<p><ins><b>D?? Deprecated C macros [depr.c.macros]</b></ins></p>
<p>
<ins>-1- The header <tt>&lt;stdalign.h&gt;</tt> has the following macro:</ins>
</p>
<blockquote><pre>
<ins>#define __alignas_is_defined 1</ins>
</pre></blockquote>
<p>
<ins>-2- The header <tt>&lt;stdbool.h&gt;</tt> has the following macro:</ins>
</p>
<blockquote><pre>
<ins>#define __bool_true_false_are_defined 1</ins>
</pre></blockquote>
</ins>

</blockquote>
</li>
</ol>

</blockquote>

<p><i>[Issaquah 2023-02-06; LWG]</i></p>

<p>
Green text additions in Clause 17 was supposed to be adding notes.
Drop them instead.
Unanimous consent (14/0/0) to move to Immediate for C++23.
</p>



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

<ol>
<li><p>Modify 17.14.4 <a href="https://wg21.link/stdalign.h.syn">[stdalign.h.syn]</a> as indicated:</p>

<blockquote>
<p><b>17.14.4 Header <tt>&lt;stdalign.h&gt;</tt> synopsis [stdalign.h.syn]</b></p>

<blockquote><pre>
<del>#define __alignas_is_defined 1</del>
</pre></blockquote>
<p>-1- The contents of the C++ header <tt>&lt;stdalign.h&gt;</tt> are the same
as the C standard library header <tt>&lt;stdalign.h&gt;</tt>, with the
following changes:
The header <tt>&lt;stdalign.h&gt;</tt> does not define
a macro named <tt>alignas</tt>.
</p>
<p><span style="font-variant: small-caps">See also</span>: ISO C 7.15</p>
</blockquote>

</li>

<li><p>Modify 17.14.5 <a href="https://wg21.link/stdbool.h.syn">[stdbool.h.syn]</a> as indicated:</p>

<blockquote>
<p><b>17.14.5 Header <tt>&lt;stdbool.h&gt;</tt> synopsis [stdbool.h.syn]</b></p>

<blockquote><pre>
<del>#define __bool_true_false_are_defined 1</del>
</pre></blockquote>
<p>-1- The contents of the C++ header <tt>&lt;stdbool.h&gt;</tt> are the same
as the C standard library header <tt>&lt;stdbool.h&gt;</tt>, with the
following changes:
The header <tt>&lt;stdbool.h&gt;</tt> does not define
macros named <tt>bool</tt>, <tt>true</tt>, or <tt>false</tt>.
</p>
<p><span style="font-variant: small-caps">See also</span>: ISO C 7.18</p>
</blockquote>
</li>

<li>Add a new subclause to Annex D <a href="https://wg21.link/depr">[depr]</a> between
D.10 <a href="https://wg21.link/depr.res.on.required">[depr.res.on.required]</a> and
D.11 <a href="https://wg21.link/depr.relops">[depr.relops]</a>, with this content:

<blockquote>
<ins>
<p><ins><b>D?? Deprecated C macros [depr.c.macros]</b></ins></p>
<p>
<ins>-1- The header <tt>&lt;stdalign.h&gt;</tt> has the following macro:</ins>
</p>
<blockquote><pre>
<ins>#define __alignas_is_defined 1</ins>
</pre></blockquote>
<p>
<ins>-2- The header <tt>&lt;stdbool.h&gt;</tt> has the following macro:</ins>
</p>
<blockquote><pre>
<ins>#define __bool_true_false_are_defined 1</ins>
</pre></blockquote>
</ins>

</blockquote>
</li>
</ol>






<hr>
<h3><a name="3828" href="https://cplusplus.github.io/LWG/lwg-active.html#3828">3828</a>. Sync <tt>intmax_t</tt> and <tt>uintmax_t</tt> with C2x</h3>
<p><b>Section:</b> 17.4.1 <a href="https://wg21.link/cstdint.syn">[cstdint.syn]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> GB <b>Opened:</b> 2022-11-10 <b>Last modified:</b> 2023-02-07</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#cstdint.syn">active issues</a> in [cstdint.syn].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#cstdint.syn">issues</a> in [cstdint.syn].</p>
<p><b>Discussion:</b></p>
<p>
This is the resolution for NB comment <b><a href="https://github.com/cplusplus/nbballot/issues/454">GB-080</a></b> 
17.4.1 [cstdint.syn] Sync <tt>intmax_t</tt> and <tt>uintmax_t</tt> with C2x.
</p>

<p>
With the approval of
<a href="https://www.open-std.org/jtc1/sc22/WG14/www/docs/n2888.htm">WG14 N2888</a>
the next C standard will resolve the long-standing issue that implementations
cannot support 128-bit integer types properly without ABI breaks.
C++ should adopt the same fix now, rather than waiting until a future
C++ standard is rebased on C2x.
</p><p>
31.13.2 <a href="https://wg21.link/cinttypes.syn">[cinttypes.syn]</a> also mentions those types, but doesn't need
a change. The proposed change allows <tt>intmax_t</tt> to be an
extended integer type of the same width as <tt>long long</tt>,
in which case we'd still want those <tt>abs</tt> overloads.
</p><p>
Recommended change:
Add to 31.13.2 <a href="https://wg21.link/cinttypes.syn">[cinttypes.syn]</a> p2 "except that <tt>intmax_t</tt> is not required to be able to 
represent all values of extended integer types wider than <tt>long long</tt>, and <tt>uintmax_t</tt> is not required 
to be able to represent all values of extended integer types wider than <tt>unsigned long long</tt>."
</p>

<p><i>[Kona 2022-11-10; Waiting for LEWG electronic polling]</i></p>


<p><i>[2022-11; LEWG electronic polling]</i></p>

<p>Unanimous consensus in favor.</p>

<p><i>[Issaquah 2023-02-06; LWG]</i></p>

<p>Unanimous consent (13/0/0) to move to Immediate for C++23.</p>



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

<ol>
<li><p>Modify 31.13.2 <a href="https://wg21.link/cinttypes.syn">[cinttypes.syn]</a> as indicated:</p>

<blockquote>
<p> -1-
The contents and meaning of the header <tt>&lt;cinttypes&gt;</tt>
are the same as the C standard library header <tt>&lt;inttypes.h&gt;</tt>,
with the following changes:
</p>
<ol style="list-style-type: none">
<li><p>(1.1) &mdash;
The header <tt>&lt;cinttypes&gt;</tt> includes the header
<tt>&lt;cstdint&gt;</tt> instead of <tt>&lt;stdint.h&gt;</tt>, and
</p></li>
<li><p><ins>(1.?) &mdash;
<tt>intmax_t</tt> and <tt>uintmax_t</tt> are not required to be able to
represent all values of extended integer types wider than <tt>long long</tt>
and <tt>unsigned long long</tt> respectively, and
</ins>
</p></li>
<li><p>(1.2) &mdash;
if and only if the type <tt>intmax_t</tt> designates an extended integer type,
the following function signatures are added:
</p>
<blockquote><pre>
intmax_t abs(intmax_t);
imaxdiv_t div(intmax_t, intmax_t);
</pre></blockquote>
<p>
which shall have the same semantics as the function signatures
<tt>intmax_t imaxabs(intmax_t)</tt> and
<tt>imaxdiv_t imaxdiv(intmax_t, intmax_t)</tt>, respectively.
</p></li>
</ol>
<p><span style="font-variant: small-caps">See also</span>: ISO C 7.8</p>
</blockquote>
</li>
</ol>






<hr>
<h3><a name="3833" href="https://cplusplus.github.io/LWG/lwg-active.html#3833">3833</a>. Remove specialization <tt>template&lt;size_t N&gt; struct formatter&lt;const charT[N], charT&gt;</tt></h3>
<p><b>Section:</b> 22.14.6.3 <a href="https://wg21.link/format.formatter.spec">[format.formatter.spec]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Mark de Wever <b>Opened:</b> 2022-11-27 <b>Last modified:</b> 2023-02-08</p>
<p><b>Priority: </b>2
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#format.formatter.spec">active issues</a> in [format.formatter.spec].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#format.formatter.spec">issues</a> in [format.formatter.spec].</p>
<p><b>Discussion:</b></p>
<p>
In the past I discussed with Victor and Charlie to remove
</p>
<blockquote><pre>
template&lt;size_t N&gt; struct formatter&lt;const charT[N], charT&gt;;
</pre></blockquote>
<p>
Charlie disliked that since MSVC STL already shipped it and Victor
mentioned it was useful. Instead of proposing to remove the
specialization in LWG <a href="https://cplusplus.github.io/LWG/lwg-defects.html#3701">3701</a> ("Make <tt>formatter&lt;remove_cvref_t&lt;const charT[N]&gt;, charT&gt;</tt> 
requirement explicit") I proposed to keep it. It's unused but it doesn't hurt. 
<p/>
That was until <a href="https://wg21.link/P2585R0">P2585R0</a> "Improve default container formatting". This paper makes it no 
longer possible to instantiate this specialization. See 
<a href="https://godbolt.org/z/bqjhhaexx">here for an example</a> and a possible work-around.
<p/>
The relevant wording is 22.14.1 <a href="https://wg21.link/format.syn">[format.syn]</a>:
</p>
<blockquote><pre>
template&lt;class R&gt;
  constexpr <i>unspecified</i> format_kind = <i>unspecified</i>;

template&lt;ranges::input_range R&gt;
    requires same_as&lt;R, remove_cvref_t&lt;R&gt;&gt;
  constexpr range_format format_kind&lt;R&gt; = <i>see below</i>;
</pre></blockquote>
<p>
combined with  22.14.7.1 <a href="https://wg21.link/format.range.fmtkind">[format.range.fmtkind]</a> p1:
</p>
<blockquote><p>
A program that instantiates the primary template of <tt>format_kind</tt> is
ill-formed.
</p></blockquote>
<p>
The issue is that <tt>const charT[N]</tt> does not satisfy the requirement
<tt>same_as&lt;R, remove_cvref_t&lt;R&gt;&gt;</tt>. So it tries to instantiate the primary
template, which is ill-formed.
<p/>
I see two possible solutions:
</p>
<ol>
<li><p><em>Removing</em> the specialization</p>
<blockquote><pre>
template&lt;size_t N&gt; struct formatter&lt;const charT[N], charT&gt;;
</pre></blockquote></li>
<li><p><em>Adding</em> a specialization</p>
<blockquote><pre>
template&lt;class charT, size_t N&gt;
  constexpr range_format format_kind&lt;const charT[N]&gt; =
    range_format::disabled;
</pre></blockquote></li>
</ol>
<p>
I discussed this issue privately and got no objection for solution 1,
therefore I propose to take that route. Implementations can still
implement solution 2 as an extension until they are ready to ship an
API/ABI break.
</p>

<p><i>[2022-11-30; Reflector poll]</i></p>

<p>
Set priority to 2 after reflector poll.
</p>
<p>
"Rationale is not really convincing why the first option is the right one."
</p>
<p>
"The point is not that we would need to add a format_kind specialization,
it is that the specialization is inconsistent with the design of <tt>formatter</tt>,
which is supposed to be instantiated only for cv-unqualified non-reference types."
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">


<p>
This wording is relative to <a href="https://wg21.link/N4917">N4917</a>.
</p>

<ol>
<li><p>Modify 22.14.6.3 <a href="https://wg21.link/format.formatter.spec">[format.formatter.spec]</a> as indicated:</p>

<blockquote>
<p>
-2- Let <tt>charT</tt> be either <tt>char</tt> or <tt>wchar_t</tt>. Each specialization 
of <tt>formatter</tt> is either enabled or disabled, as described below. A 
<i>debug-enabled</i> specialization of <tt>formatter</tt> additionally provides a public, constexpr,
non-static member function <tt>set_debug_format()</tt> which modifies the state of the <tt>formatter</tt> 
to be as if the type of the <i>std-format-spec</i> parsed by the last call to <tt>parse</tt> were <tt>?</tt>. 
Each header that declares the template <tt>formatter</tt> provides the following enabled specializations:
</p>
<ol style="list-style-type: none">
<li><p>(2.1) &mdash; The debug-enabled specializations [&hellip;]</p></li>
<li><p>(2.2) &mdash; For each <tt>charT</tt>, the debug-enabled string type specializations</p>
<blockquote><pre>
template&lt;&gt; struct formatter&lt;charT*, charT&gt;;
template&lt;&gt; struct formatter&lt;const charT*, charT&gt;;
template&lt;size_t N&gt; struct formatter&lt;charT[N], charT&gt;;
<del>template&lt;size_t N&gt; struct formatter&lt;const charT[N], charT&gt;;</del>
template&lt;class traits, class Allocator&gt;
  struct formatter&lt;basic_string&lt;charT, traits, Allocator&gt;, charT&gt;;
template&lt;class traits&gt;
  struct formatter&lt;basic_string_view&lt;charT, traits&gt;, charT&gt;;
</pre></blockquote></li>
<li><p>(2.3) &mdash; [&hellip;]</p></li>
<li><p>(2.4) &mdash; [&hellip;]</p></li>
</ol>
</blockquote>
</li>

<li><p>Add a new paragraph to C.1.9 <a href="https://wg21.link/diff.cpp20.utilities">[diff.cpp20.utilities]</a> as indicated:</p>

<blockquote>
<p>
<ins><b>Affected subclause</b>: 22.14.6.3 <a href="https://wg21.link/format.formatter.spec">[format.formatter.spec]</a></ins>
<p/>
<ins><b>Change</b>: Remove the <tt>formatter</tt> specialization
<tt>template&lt;size_t N&gt; struct formatter&lt;const charT[N], charT&gt;</tt>.</ins>
<p/>
<ins><b>Rationale</b>: The <tt>formatter</tt> specialization was not used in the Standard library.
Keeping the specialization well-formed required an additional <tt>format_kind</tt>
specialization.</ins>
<p/>
<ins><b>Effect on original feature</b>: Valid C++ 2020 code that instantiated the removed
specialization is now ill-formed.</ins>
</p>
</blockquote>
</li>
</ol>
</blockquote>


<p><i>[2023-02-07 Tim provides updated wording]</i></p>


<p><i>[Issaquah 2023-02-08; LWG]</i></p>

<p>Unanimous consent to move to Immediate.</p>



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

<ol>
<li><p>Modify 22.14.6.3 <a href="https://wg21.link/format.formatter.spec">[format.formatter.spec]</a> as indicated:</p>

<blockquote>
<p>
-2- Let <tt>charT</tt> be either <tt>char</tt> or <tt>wchar_t</tt>. Each specialization 
of <tt>formatter</tt> is either enabled or disabled, as described below. A 
<i>debug-enabled</i> specialization of <tt>formatter</tt> additionally provides a public, constexpr,
non-static member function <tt>set_debug_format()</tt> which modifies the state of the <tt>formatter</tt> 
to be as if the type of the <i>std-format-spec</i> parsed by the last call to <tt>parse</tt> were <tt>?</tt>. 
Each header that declares the template <tt>formatter</tt> provides the following enabled specializations:
</p>
<ol style="list-style-type: none">
<li><p>(2.1) &mdash; The debug-enabled specializations [&hellip;]</p></li>
<li><p>(2.2) &mdash; For each <tt>charT</tt>, the debug-enabled string type specializations</p>
<blockquote><pre>
template&lt;&gt; struct formatter&lt;charT*, charT&gt;;
template&lt;&gt; struct formatter&lt;const charT*, charT&gt;;
template&lt;size_t N&gt; struct formatter&lt;charT[N], charT&gt;;
<del>template&lt;size_t N&gt; struct formatter&lt;const charT[N], charT&gt;;</del>
template&lt;class traits, class Allocator&gt;
  struct formatter&lt;basic_string&lt;charT, traits, Allocator&gt;, charT&gt;;
template&lt;class traits&gt;
  struct formatter&lt;basic_string_view&lt;charT, traits&gt;, charT&gt;;
</pre></blockquote></li>
<li><p>(2.3) &mdash; [&hellip;]</p></li>
<li><p>(2.4) &mdash; [&hellip;]</p></li>
</ol>
</blockquote>
</li>

<li><p>Add a new paragraph to C.1.9 <a href="https://wg21.link/diff.cpp20.utilities">[diff.cpp20.utilities]</a> as indicated:</p>

<blockquote>
<p>
<ins><b>Affected subclause</b>: 22.14.6.3 <a href="https://wg21.link/format.formatter.spec">[format.formatter.spec]</a></ins>
<p/>
<ins><b>Change</b>: Removed the <tt>formatter</tt> specialization
<tt>template&lt;size_t N&gt; struct formatter&lt;const charT[N], charT&gt;</tt>.</ins>
<p/>
<ins><b>Rationale</b>: The specialization is inconsistent with the design of <tt>formatter</tt>,
which is intended to be instantiated only with cv-unqualified object types.</ins>
<p/>
<ins><b>Effect on original feature</b>: Valid C++ 2020 code that instantiated the removed
specialization can become ill-formed.</ins>
</p>
</blockquote>
</li>
</ol>






<hr>
<h3><a name="3836" href="https://cplusplus.github.io/LWG/lwg-active.html#3836">3836</a>. <tt>std::expected&lt;bool, E1&gt;</tt> conversion constructor <tt>expected(const expected&lt;U, G&gt;&amp;)</tt> 
should take precedence over <tt>expected(U&amp;&amp;)</tt> with operator <tt>bool</tt></h3>
<p><b>Section:</b> 22.8.6.2 <a href="https://wg21.link/expected.object.cons">[expected.object.cons]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Hui Xie <b>Opened:</b> 2022-11-30 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>1
</p>
<p><b>Discussion:</b></p>
<p>
The issue came up when implementing <tt>std::expected</tt> in libc++. Given the following example:
</p>
<blockquote><pre>
struct BaseError{};
struct DerivedError : BaseError{};

std::expected&lt;int, DerivedError&gt; e1(5);  
std::expected&lt;int, BaseError&gt; e2(e1);  // <span style="color:green;font-weight:bold">e2 holds 5</span>
</pre></blockquote>
<p>
In the above example, <tt>e2</tt> is constructed with the conversion constructor
</p>
<blockquote><pre>
expected::expected(const expected&lt;U, G&gt;&amp;)
</pre></blockquote>
<p>
and the value <tt>5</tt> is correctly copied into <tt>e2</tt> as expected.
<p/>
However, if we change the type from <tt>int</tt> to <tt>bool</tt>, the behaviour is very surprising.
</p>
<blockquote><pre>
std::expected&lt;bool, DerivedError&gt; e1(false);
std::expected&lt;bool, BaseError&gt; e2(e1);  // <span style="color:red;font-weight:bolder">e2 holds true</span>
</pre></blockquote>
<p>
In this example <tt>e2</tt> is constructed with
</p>
<blockquote><pre>
expected::expected(U&amp;&amp;)
</pre></blockquote>
<p>
together with
</p>
<blockquote><pre>
expected::operator bool() const
</pre></blockquote>
<p>
Instead of copying <tt>e1</tt>'s "<tt>false</tt>" into <tt>e2</tt>, it uses <tt>operator bool</tt>, which returns 
<tt>true</tt> in this case and <tt>e2</tt> would hold "<tt>true</tt>" instead.
<p/>
This is surprising behaviour given how inconsistent between <tt>int</tt> and <tt>bool</tt>.
<p/>
The reason why the second example uses a different overload is that the constructor 
<tt>expected(const expected&lt;U, G&gt;&amp; rhs);</tt> has the following constraint
(22.8.6.2 <a href="https://wg21.link/expected.object.cons">[expected.object.cons]</a> p17):
</p>
<blockquote>
<ol style="list-style-type: none">
<li><p>(17.3) &mdash; <tt>is_constructible_v&lt;T, expected&lt;U, G&gt;&amp;&gt;</tt> is <tt>false</tt>; and</p></li>
<li><p>(17.4) &mdash; <tt>is_constructible_v&lt;T, expected&lt;U, G&gt;&gt;</tt> is <tt>false</tt>; and</p></li>
<li><p>(17.5) &mdash; <tt>is_constructible_v&lt;T, const expected&lt;U, G&gt;&amp;&gt;</tt> is <tt>false</tt>; and</p></li>
<li><p>(17.6) &mdash; <tt>is_constructible_v&lt;T, const expected&lt;U, G&gt;&gt;</tt> is <tt>false</tt>; and</p></li>
<li><p>(17.7) &mdash; <tt>is_convertible_v&lt;expected&lt;U, G&gt;&amp;, T&gt;</tt> is <tt>false</tt>; and</p></li>
<li><p>(17.8) &mdash; <tt>is_convertible_v&lt;expected&lt;U, G&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>; and</p></li>
<li><p>(17.9) &mdash; <tt>is_convertible_v&lt;const expected&lt;U, G&gt;&amp;, T&gt;</tt> is <tt>false</tt>; and</p></li>
<li><p>(17.10) &mdash; <tt>is_convertible_v&lt;const expected&lt;U, G&gt;&amp;&amp;, T&gt;</tt> is <tt>false</tt>; and</p></li>
</ol>
</blockquote>
<p>
Since <tt>T</tt> is <tt>bool</tt> in the second example, and <tt>bool</tt> can be constructed <tt>from</tt> 
<tt>std::expected</tt>, this overload will be removed. and the overload that takes <tt>U&amp;&amp;</tt> will be selected.
<p/>
I would suggest to special case <tt>bool</tt>, i.e.
</p>
<ul>
<li><p>(The above 8 constraints); or</p></li>
<li><p><tt>is_same_v&lt;remove_cv_t&lt;T&gt;, bool&gt;</tt> is <tt>true</tt></p></li>
</ul>
<p>
And we need to make sure this overload and the overload that takes <tt>expected(U&amp;&amp;)</tt> be mutually exclusive.
</p>

<p><i>[2023-01-06; Reflector poll]</i></p>

<p>
Set priority to 1 after reflector poll.
</p>
<p>
There was a mix of votes for P1 and P2 but also one for NAD
("The design of forward/repack construction for expected matches optional,
when if the stored value can be directly constructed, we use that.").
<code>std::optional&lt;bool&gt;</code> is similarly affected.
Any change should consider the effects on
<code>expected&lt;expected&lt;&gt;&gt;</code> use cases.
</p>

<p><i>[Issaquah 2023-02-08; Jonathan provides wording]</i></p>

<p><i>[Issaquah 2023-02-09; LWG]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>
<li><p>Modify 22.5.3.2 <a href="https://wg21.link/optional.ctor">[optional.ctor]</a> as indicated:</p>
<blockquote>
<pre><code>
template&lt;class U = T&gt; constexpr explicit(<i>see below</i>) optional(U&amp;&amp; v);
</code></pre>
<p>-23- <i>Constraints</i>:
<blockquote class="note">
[<i>Drafting note</i>: Change this paragraph to a bulleted list.]
</blockquote>
<ul>
<li><ins>(23.1) &mdash;</ins>
<tt>is_constructible_v&lt;T, U&gt;</tt> is <tt>true</tt>,
</li>
<li><ins>(23.2) &mdash;</ins>
<tt>is_same_v&lt;remove_cvref_t&lt;U&gt;, in_place_t&gt;</tt> is <tt>false</tt>,
<del>and</del>
</li>
<li><ins>(23.3) &mdash;</ins>
<tt>is_same_v&lt;remove_cvref_t&lt;U&gt;, optional&gt;</tt> is <tt>false</tt><ins>, and</ins>
</li>
<li><ins>(23.4) &mdash;
if <tt>T</tt> is <i>cv</i> <tt>bool</tt>,
<tt>remove_cvref_t&lt;U&gt;</tt> is not a specialization of <tt>optional</tt></ins>.
</li>
</ul>
</p>
<p>-24- <i>Effects</i>:
Direct-non-list-initializes the contained value with
<tt>std::forward&gt;U&gt;(v)</tt>.
</p>
<p>-25- <i>Postconditions</i>:
<tt>*this</tt> has a value.
</p>
<p>-26- <i>Throws</i>:
Any exception thrown by the selection constructor of <tt>T</tt>.
</p>
<p>-27- <i>Remarks</i>: If <tt>T</tt>'s selected constructor is a constexpr constructor,
this constructor is a constexpr constructor.
The expression inside <tt>explicit</tt> is equivalent to:<br/>
<pre>  !is_convertible_v&lt;U, T&gt;</pre>
</p>

<pre><code>
template&lt;class U&gt; constexpr explicit(<i>see below</i>) optional(const optional&lt;U&gt;&amp; rhs);
</code></pre>
<p>-28- <i>Constraints</i>:
<ul>
<li>(28.1) &mdash;
<tt>is_constructible_v&lt;T, const U&amp;&gt;</tt> is <tt>true</tt>,
and
</li>
<li>(28.1) &mdash;
<ins>if <tt>T</tt> is not <i>cv</i> <tt>bool</tt>,</ins>
<tt><i>converts-from-any-cvref</i>&lt;T, optional&lt;U&gt;&gt;</tt> is <tt>false</tt>.
</li>
</ul>
</p>
<p>-29- <i>Effects</i>:
If <tt>rhs</tt> contains a value,
direct-non-list-initializes the contained value with
<tt>*rhs</tt>.
</p>
<p>-30- <i>Postconditions</i>:
<tt>rhs.has_value() == this->has_value()</tt>.
</p>
<p>-31- <i>Throws</i>:
Any exception thrown by the selection constructor of <tt>T</tt>.
</p>
<p>-32- <i>Remarks</i>: The expression inside <tt>explicit</tt> is equivalent to:<br/>
<pre>  !is_convertible_v&lt;const U&amp;, T&gt;</pre>
</p>

<pre><code>
template&lt;class U&gt; constexpr explicit(<i>see below</i>) optional(optional&lt;U&gt;&amp;&amp; rhs);
</code></pre>
<p>-33- <i>Constraints</i>:
<ul>
<li>(33.1) &mdash;
<tt>is_constructible_v&lt;T, U&gt;</tt> is <tt>true</tt>,
and
</li>
<li>(33.1) &mdash;
<ins>if <tt>T</tt> is not <i>cv</i> <tt>bool</tt>,</ins>
<tt><i>converts-from-any-cvref</i>&lt;T, optional&lt;U&gt;&gt;</tt> is <tt>false</tt>.
</li>
</ul>
</p>
<p>-34- <i>Effects</i>:
If <tt>rhs</tt> contains a value,
direct-non-list-initializes the contained value with
<tt>std::move(*rhs)</tt>.
<tt>rhs.has_value()</tt> is unchanged.
</p>
<p>-35- <i>Postconditions</i>:
<tt>rhs.has_value() == this->has_value()</tt>.
</p>
<p>-36- <i>Throws</i>:
Any exception thrown by the selection constructor of <tt>T</tt>.
</p>
<p>-37- <i>Remarks</i>: The expression inside <tt>explicit</tt> is equivalent to:<br/>
<pre>  !is_convertible_v&lt;U, T&gt;</pre>
</p>

</blockquote>
</li>

<li><p>Modify 22.8.6.2 <a href="https://wg21.link/expected.object.cons">[expected.object.cons]</a> as indicated:</p>
<blockquote>
<pre><code>
template&lt;class U, class G&gt;
  constexpr explicit(see below) expected(const expected&lt;U, G&gt;&amp; rhs);
template&lt;class U, class G&gt;
  constexpr explicit(see below) expected(expected&lt;U, G&gt;&amp;&amp; rhs);
</code></pre>
<p>-17- Let:
<ul>
<li>(17.1) &mdash;
<tt>UF</tt> be <tt>const U&amp;</tt> for the first overload and <tt>U</tt> for the second overload.
</li>
<li>(17.2) &mdash;
<tt>GF</tt> be <tt>const G&amp;</tt> for the first overload and <tt>G</tt> for the second overload.
</li>
</ul>
</p>
<p>-18- <i>Constraints</i>:
<ul>
<li>(18.1) &mdash;
<tt>is_constructible_v&lt;T, UF&gt;</tt> is <tt>true</tt>; and
</li>
<li>(18.2) &mdash;
<tt>is_constructible_v&lt;E, GF&gt;</tt> is <tt>true</tt>; and
</li>
<li>(18.3) &mdash;
<ins>if <tt>T</tt> is not <i>cv</i> <tt>bool</tt>,</ins>
<tt><i>converts-from-any-cvref</i>&lt;T, expected&lt;U, G&gt;&gt;</tt> is <tt>false</tt>; and
</li>
<li>(18.4) &mdash;
<tt>is_constructible_v&lt;unexpected&lt;E&gt;, expected&lt;U, G&gt;&amp;&gt;</tt> is <tt>false</tt>; and
</li>
<li>(18.5) &mdash;
<tt>is_constructible_v&lt;unexpected&lt;E&gt;, expected&lt;U, G&gt;&gt;</tt> is <tt>false</tt>; and
</li>
<li>(18.6) &mdash;
<tt>is_constructible_v&lt;unexpected&lt;E&gt;, const expected&lt;U, G&gt;&amp;&gt;</tt> is <tt>false</tt>; and
</li>
<li>(18.7) &mdash;
<tt>is_constructible_v&lt;unexpected&lt;E&gt;, const expected&lt;U, G&gt;&gt;</tt> is <tt>false</tt>.
</li>
</ul>
</p>
<p>-19- <i>Effects</i>:
If <tt>rhs.has_value()</tt>,
direct-non-list-initializes <tt><i>val</i></tt> with
<tt>std::forward&gt;UF&gt;(*rhs)</tt>.
Otherwise, direct-non-list-initializes <tt><i>unex</i></tt>
with <tt>std::forward&gt;GF&gt;(rhs.error())</tt>.
</p>
<p>-20- <i>Postconditions</i>:
<tt>rhs.has_value()</tt> is unchanged;
<tt>rhs.has_value() == this->has_value()</tt> is <tt>true</tt>.
</p>
<p>-21- <i>Throws</i>:
Any exception thrown by the initialization of <tt><i>val</i></tt> or <tt><i>unex</i></tt>.
</p>
<p>-22- <i>Remarks</i>: The expression inside <tt>explicit</tt> is equivalent to
<tt>!is_convertible_v&lt;UF, T&gt; || !is_convertible_v&lt;GF, E&gt;</tt>.
</p>

<pre><code>
template&lt;class U = T&gt;
  constexpr explicit(!is_convertible_v&lt;U, T&gt;) expected(U&amp;&amp; v);
</code></pre>
<p>-23- <i>Constraints</i>:
<ul>
<li>(23.1) &mdash;
<tt>is_same_v&lt;remove_cvref_t&lt;U&gt;, in_place_t&gt;</tt> is <tt>false</tt>; and
</li>
<li>(23.2) &mdash;
<tt>is_same_v&lt;expected, remove_cvref_t&lt;U&gt;&gt;</tt> is <tt>false</tt>; and
</li>
<li>(23.3) &mdash;
<tt>is_constructible_v&lt;T, U&gt;</tt> is <tt>true</tt>; and
</li>
<li>(23.4) &mdash;
<tt>remove_cvref_t&lt;U&gt;</tt> is not a specialization of <tt>unexpected</tt><ins>; and</ins>
</li>
<li><ins>(23.5) &mdash;
if <tt>T</tt> is <i>cv</i> <tt>bool</tt>,
<tt>remove_cvref_t&lt;U&gt;</tt> is not a specialization of <tt>expected</tt></ins>.
</li>
</ul>
</p>
<p>-24- <i>Effects</i>:
Direct-non-list-initializes <tt><i>val</i></tt> with
<tt>std::forward&gt;U&gt;(v)</tt>.
</p>
<p>-25- <i>Postconditions</i>:
<tt>has_value()</tt> is <tt>true</tt>.
</p>
<p>-26- <i>Throws</i>:
Any exception thrown by the initialization of <tt><i>val</i></tt>.
</p>

</blockquote>
</li>
</ol>





<hr>
<h3><a name="3843" href="https://cplusplus.github.io/LWG/lwg-active.html#3843">3843</a>. <tt>std::expected&lt;T,E&gt;::value() &amp;</tt> assumes <tt>E</tt> is copy constructible</h3>
<p><b>Section:</b> 22.8.6.6 <a href="https://wg21.link/expected.object.obs">[expected.object.obs]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Jonathan Wakely <b>Opened:</b> 2022-12-20 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
22.8.6.6 <a href="https://wg21.link/expected.object.obs">[expected.object.obs]</a> p9 says:
</p>
<blockquote>
<i>Throws</i>:
<tt>bad_expected_access(error())</tt> if <tt>has_value()</tt> is <tt>false</tt>.
</blockquote>
<p>
But if <tt>error()</tt> returns a reference to a move-only type
then it can't be copied and the function body is ill-formed.
Should it be constrained with <tt>is_copy_constructible_v&lt;E&gt;</tt>?
Or just mandate it?
</p>
<p>
Similarly, the <tt>value()&amp;&amp;</tt> and <tt>value() const&amp;&amp;</tt>
overloads require <tt>is_move_constructible_v&lt;E&gt;</tt> to be true
for <tt>bad_expected_access(std::move(error()))</tt> to be valid.
Casey Carter pointed out they also require it to be copyable so that the
exception can be thrown, as per 14.2 <a href="https://wg21.link/except.throw">[except.throw]</a> p5.
</p>

<p><i>[Issaquah 2023-02-09; LWG]</i></p>

<p>Move to Immediate for C++23</p>



<p id="res-3843"><b>Proposed resolution:</b></p>
<ol>
<li>
<p> Modify 22.8.6.6 <a href="https://wg21.link/expected.object.obs">[expected.object.obs]</a> as indicated: </p>
<blockquote>
<blockquote><pre>
constexpr const T&amp; value() const &amp;;
constexpr T&amp; value() &amp;;
</pre></blockquote>
<p><ins>-?-
<i>Mandates</i>: <tt>is_copy_constructible_v&lt;E&gt;</tt> is <tt>true</tt>.
</ins>
</p>
<p>-8-
<i>Returns</i>:
<tt>val</tt>, if <tt>has_value()</tt> is <tt>true</tt>.
</p>
<p>-9-
<i>Throws</i>:
<tt>bad_expected_access(<ins>as_const(</ins>error()<ins>)</ins>)</tt>
if <tt>has_value()</tt> is <tt>false</tt>.
</p>
<blockquote><pre>
constexpr T&amp;&amp; value() &amp;&amp;;
constexpr const T&amp;&amp; value() const &amp;&amp;;
</pre></blockquote>
<p><ins>-?-
<i>Mandates</i>: <tt>is_copy_constructible_v&lt;E&gt;</tt> is <tt>true</tt>
and <tt>is_constructible_v&lt;E, decltype(std::move(error()))&gt;</tt> is <tt>true</tt>.
</ins>
</p>
<p>-10-
<i>Returns</i>:
<tt>std::move(val)</tt>, if <tt>has_value()</tt> is <tt>true</tt>.
</p>
<p>-11-
<i>Throws</i>:
<tt>bad_expected_access(std::move(error()))</tt>
if <tt>has_value()</tt> is <tt>false</tt>.
</p>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3847" href="https://cplusplus.github.io/LWG/lwg-active.html#3847">3847</a>. <tt>ranges::to</tt> can still return views</h3>
<p><b>Section:</b> 26.5.7.2 <a href="https://wg21.link/range.utility.conv.to">[range.utility.conv.to]</a>, 26.5.7.3 <a href="https://wg21.link/range.utility.conv.adaptors">[range.utility.conv.adaptors]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2023-01-06 <b>Last modified:</b> 2023-02-08</p>
<p><b>Priority: </b>2
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#range.utility.conv.to">active issues</a> in [range.utility.conv.to].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#range.utility.conv.to">issues</a> in [range.utility.conv.to].</p>
<p><b>Discussion:</b></p>
<p>
The intention of <tt>ranges::to</tt> is to construct a non-view object,
which is reflected in its constraint that object type <tt>C</tt> should not
model a <tt>view</tt>.
</p>
<p>
The specification allows <tt>C</tt> to be a <tt>const</tt>-qualified type
which does not satisfy <tt>view</tt> such as <tt>const string_view</tt>,
making <tt>ranges::to</tt> return a dangling view. We should ban such cases.
</p>

<p><i>[2023-02-01; Reflector poll]</i></p>

<p>
Set priority to 2 after reflector poll.
Just require C to be a cv-unqualified object type.
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
<p>
This wording is relative to <a href="https://wg21.link/N4917">N4917</a>.
</p>
<ol>
<li><p>Modify 26.2 <a href="https://wg21.link/ranges.syn">[ranges.syn]</a> as indicated:</p>

<blockquote>
<pre>#include &lt;compare&gt;              // <i>see 17.11.1 <a href="https://wg21.link/compare.syn">[compare.syn]</a></i>
#include &lt;initializer_list&gt;     // <i>see 17.10.2 <a href="https://wg21.link/initializer.list.syn">[initializer.list.syn]</a></i>
#include &lt;iterator&gt;             // <i>see 25.2 <a href="https://wg21.link/iterator.synopsis">[iterator.synopsis]</a></i>

namespace std::ranges {
  […]
  // <i>26.5.7 <a href="https://wg21.link/range.utility.conv">[range.utility.conv]</a>, range conversions</i>
  template&lt;class C, input_range R, class... Args&gt; requires (!view&lt;<ins>remove_cv_t&lt;</ins>C<ins>&gt;</ins>&gt;)
    constexpr C to(R&amp;&amp; r, Args&amp;&amp;... args);                                          // <i>freestanding</i>
  template&lt;template&lt;class...&gt; class C, input_range R, class... Args&gt;
    constexpr auto to(R&amp;&amp; r, Args&amp;&amp;... args);                                       // <i>freestanding</i>
  template&lt;class C, class... Args&gt; requires (!view&lt;<ins>remove_cv_t&lt;</ins>C<ins>&gt;</ins>&gt;)
    constexpr auto to(Args&amp;&amp;... args);                                              // <i>freestanding</i>
  template&lt;template&lt;class...&gt; class C, class... Args&gt;
    constexpr auto to(Args&amp;&amp;... args);                                              // <i>freestanding</i>
  […]
}
</pre>
</blockquote>
</li><li><p>Modify 26.5.7.2 <a href="https://wg21.link/range.utility.conv.to">[range.utility.conv.to]</a> as indicated:</p>
<blockquote>
<pre>template&lt;class C, input_range R, class... Args&gt; requires (!view&lt;<ins>remove_cv_t&lt;</ins>C<ins>&gt;</ins>&gt;)
constexpr C to(R&amp;&amp; r, Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
-1- <i>Returns</i>: An object of type <tt>C</tt> constructed from the elements of <tt>r</tt> in the following manner:
</p>
[…]
</blockquote>
</blockquote>
</li>
<li><p>Modify 26.5.7.3 <a href="https://wg21.link/range.utility.conv.adaptors">[range.utility.conv.adaptors]</a> as indicated:</p>
<blockquote>
<pre>template&lt;class C, class... Args&gt; requires (!view&lt;<ins>remove_cv_t&lt;</ins>C<ins>&gt;</ins>&gt;)
  constexpr auto to(Args&amp;&amp;... args);
template&lt;template&lt;class...&gt; class C, class... Args&gt;
  constexpr auto to(Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
-1- <i>Returns</i>: A range adaptor closure object (26.7.2 <a href="https://wg21.link/range.adaptor.object">[range.adaptor.object]</a>) <tt>f</tt> that is a perfect forwarding call wrapper (22.10.4 <a href="https://wg21.link/func.require">[func.require]</a>) with the following properties:
</p>
[…]
</blockquote>
</blockquote>
</li>
</ol>
</blockquote>

<p><i>[2023-02-02; Jonathan provides improved wording]</i></p>


<p><i>[Issaquah 2023-02-08; LWG]</i></p>

<p>
Unanimous consent to move to Immediate.
This also resolves LWG <a href="https://cplusplus.github.io/LWG/lwg-active.html#3787">3787</a>.
</p>



<p id="res-3847"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4928">N4928</a>.
</p>
<ol>
<li><p>Modify 26.5.7.2 <a href="https://wg21.link/range.utility.conv.to">[range.utility.conv.to]</a> as indicated:</p>
<blockquote>
<pre>template&lt;class C, input_range R, class... Args&gt; requires (!view&lt;C&gt;)
constexpr C to(R&amp;&amp; r, Args&amp;&amp;... args);
</pre>
<blockquote>
<p><ins>-?- <i>Mandates</i>: <tt>C</tt> is a cv-unqualified class type.</ins></p>
<p>
-1- <i>Returns</i>: An object of type <tt>C</tt> constructed from the elements of <tt>r</tt> in the following manner:
</p>
[…]
</blockquote>
</blockquote>
</li>
<li><p>Modify 26.5.7.3 <a href="https://wg21.link/range.utility.conv.adaptors">[range.utility.conv.adaptors]</a> as indicated:</p>
<blockquote>
<pre>template&lt;class C, class... Args&gt; requires (!view&lt;C&gt;)
  constexpr auto to(Args&amp;&amp;... args);
template&lt;template&lt;class...&gt; class C, class... Args&gt;
  constexpr auto to(Args&amp;&amp;... args);
</pre>
<blockquote>
<p><ins>-?- <i>Mandates</i>: For the first overload, <tt>C</tt> is a cv-unqualified class type.</ins></p>
<p>
-1- <i>Returns</i>: A range adaptor closure object (26.7.2 <a href="https://wg21.link/range.adaptor.object">[range.adaptor.object]</a>) <tt>f</tt> that is a perfect forwarding call wrapper (22.10.4 <a href="https://wg21.link/func.require">[func.require]</a>) with the following properties:
</p>
[…]
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3862" href="https://cplusplus.github.io/LWG/lwg-active.html#3862">3862</a>. <tt>basic_const_iterator</tt>'s <tt>common_type</tt> specialization is underconstrained</h3>
<p><b>Section:</b> 25.2 <a href="https://wg21.link/iterator.synopsis">[iterator.synopsis]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2023-01-25 <b>Last modified:</b> 2023-02-07</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#iterator.synopsis">issues</a> in [iterator.synopsis].</p>
<p><b>Discussion:</b></p>
<p>
To make <tt>basic_const_iterator</tt> compatible with its unwrapped iterators, the standard defines the following
<tt>common_type</tt> specialization:
</p>
<blockquote><pre>
template&lt;class T, common_with&lt;T&gt; U&gt;
struct common_type&lt;basic_const_iterator&lt;T&gt;, U&gt; {
  using type = basic_const_iterator&lt;common_type_t&lt;T, U&gt;&gt;;
};
</pre></blockquote>
<p>
For type <tt>U</tt>, when it shares a common type with the unwrapped type <tt>T</tt> of <tt>basic_const_iterator</tt>,
the common type of both is <tt>basic_const_iterator</tt> of the common type of <tt>T</tt> and <tt>U</tt>.
<p/>
However, since this specialization only constrains <tt>U</tt> and <tt>T</tt> to have a common type,
this allows <tt>U</tt> to be any type that satisfies such requirement, such as <tt>optional&lt;T&gt;</tt>,
in which case computing the common type of both would produce a hard error inside the specialization,
because <tt>basic_const_iterator</tt> requires the template parameter to be <tt>input_iterator</tt>,
while <tt>optional</tt> clearly isn't.
</p>
<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
<p>
This wording is relative to <a href="https://wg21.link/N4928">N4928</a>.
</p>

<ol>
<li><p>Modify 25.2 <a href="https://wg21.link/iterator.synopsis">[iterator.synopsis]</a>, header <tt>&lt;iterator&gt;</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
#include &lt;compare&gt;              // <i>see 17.11.1 <a href="https://wg21.link/compare.syn">[compare.syn]</a></i>
#include &lt;concepts&gt;             // <i>see 18.3 <a href="https://wg21.link/concepts.syn">[concepts.syn]</a></i>

namespace std {
  [&hellip;]
  template&lt;class T, common_with&lt;T&gt; U&gt;
    <ins>requires input_iterator&lt;U&gt;</ins>
  struct common_type&lt;basic_const_iterator&lt;T&gt;, U&gt; {                                  // <i>freestanding</i>
    using type = basic_const_iterator&lt;common_type_t&lt;T, U&gt;&gt;;
  };
  template&lt;class T, common_with&lt;T&gt; U&gt;
    <ins>requires input_iterator&lt;U&gt;</ins>
  struct common_type&lt;U, basic_const_iterator&lt;T&gt;&gt; {                                  // <i>freestanding</i>
    using type = basic_const_iterator&lt;common_type_t&lt;T, U&gt;&gt;;
  };
  [&hellip;]
}
</pre>
</blockquote>
</li>

</ol>
</blockquote>

<p><i>[2023-02-06; Jonathan provides improved wording based on Casey's
suggestion during the prioritization poll.]</i></p>


<p><i>[Issaquah 2023-02-07; LWG]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>
<li><p>Modify 25.2 <a href="https://wg21.link/iterator.synopsis">[iterator.synopsis]</a>, header <tt>&lt;iterator&gt;</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
#include &lt;compare&gt;              // <i>see 17.11.1 <a href="https://wg21.link/compare.syn">[compare.syn]</a></i>
#include &lt;concepts&gt;             // <i>see 18.3 <a href="https://wg21.link/concepts.syn">[concepts.syn]</a></i>

namespace std {
  [&hellip;]
  template&lt;class T, common_with&lt;T&gt; U&gt;
    <ins>requires input_iterator&lt;common_type_t&lt;T, U&gt;&gt;</ins>
  struct common_type&lt;basic_const_iterator&lt;T&gt;, U&gt; {                                  // <i>freestanding</i>
    using type = basic_const_iterator&lt;common_type_t&lt;T, U&gt;&gt;;
  };
  template&lt;class T, common_with&lt;T&gt; U&gt;
    <ins>requires input_iterator&lt;common_type_t&lt;T, U&gt;&gt;</ins>
  struct common_type&lt;U, basic_const_iterator&lt;T&gt;&gt; {                                  // <i>freestanding</i>
    using type = basic_const_iterator&lt;common_type_t&lt;T, U&gt;&gt;;
  };
  template&lt;class T, common_with&lt;T&gt; U&gt;
    <ins>requires input_iterator&lt;common_type_t&lt;T, U&gt;&gt;</ins>
  struct common_type&lt;basic_const_iterator&lt;T&gt;, basic_const_iterator&lt;U&gt;&gt; {            // <i>freestanding</i>
    using type = basic_const_iterator&lt;common_type_t&lt;T, U&gt;&gt;;
  };
  [&hellip;]
}
</pre>
</blockquote>
</li>

</ol>





<hr>
<h3><a name="3865" href="https://cplusplus.github.io/LWG/lwg-active.html#3865">3865</a>. Sorting a range of <tt>pair</tt>s</h3>
<p><b>Section:</b> 22.3.3 <a href="https://wg21.link/pairs.spec">[pairs.spec]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Barry Revzin <b>Opened:</b> 2023-01-28 <b>Last modified:</b> 2023-02-09</p>
<p><b>Priority: </b>2
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#pairs.spec">active issues</a> in [pairs.spec].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#pairs.spec">issues</a> in [pairs.spec].</p>
<p><b>Discussion:</b></p>
<p>
Consider this example:
</p>
<blockquote><pre>
#include &lt;algorithm&gt;
#include &lt;ranges&gt;

int main() {
  int a[3] = {1, 2, -1};
  int b[3] = {1, 4, 1};
  std::ranges::sort(std::views::zip(a, b));
}
</pre></blockquote>
<p>
This is currently valid C++23 code, but wasn't before <a href="https://wg21.link/P2165">P2165</a> (Compatibility between <tt>tuple</tt>, <tt>pair</tt> 
and <i>tuple-like</i> objects). Before P2165, <tt>zip(a, b)</tt> returned a range whose reference was 
<tt>std::pair&lt;int&amp;, int&amp;&gt;</tt> and whose <tt>value_type</tt> was <tt>std::pair&lt;int, int&gt;</tt> and 
<tt>std::pair</tt>, unlike <tt>std::tuple</tt>, does not have any heterogeneous comparisons &mdash; which is required to 
satisfy the <tt>sortable</tt> concept. 
<p/>
While the zip family of range adapters no longer has this problem, nothing prevents users from themselves creating a range 
whose reference type is <tt>pair&lt;T&amp;, U&amp;&gt;</tt> and whose <tt>value_type</tt> is <tt>pair&lt;T, U&gt;</tt> 
(which is now a valid range after the zip paper) and then discovering that this range isn't sortable, even though the 
equivalent using <tt>tuple</tt> is. 
<p/>
Suggested resolution:
<p/>
Change <tt>pair</tt>'s comparison operators from comparing two arguments of type <tt>const pair&lt;T1, T2&gt;&amp;</tt> 
to instead comparing arguments of types <tt>const pair&lt;T1, T2&gt;&amp;</tt> and <tt>const pair&lt;U1, U2&gt;&amp;</tt>. 
</p>

<p><i>[2023-02-05; Barry provides wording]</i></p>


<p><i>[2023-02-06; Reflector poll]</i></p>

<p>
Set priority to 2 after reflector poll.
</p>

<p><i>[Issaquah 2023-02-07; LWG]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>
<li><p>Modify 22.2.1 <a href="https://wg21.link/utility.syn">[utility.syn]</a>, header <tt>&lt;utility&gt;</tt> synopsis, as indicated:</p>

<blockquote>
<pre>
[&hellip;]
// <i>22.3.3 <a href="https://wg21.link/pairs.spec">[pairs.spec]</a>, pair specialized algorithms</i>
template&lt;class T1, class T2<ins>, class U1, class U2</ins>&gt;
  constexpr bool operator==(const pair&lt;T1, T2&gt;&amp;, const pair&lt;<del>T</del><ins>U</ins>1, <del>T</del><ins>U</ins>2&gt;&amp;);
template&lt;class T1, class T2<ins>, class U1, class U2</ins>&gt;
  constexpr common_comparison_category_t&lt;<i>synth-three-way-result</i>&lt;T1<ins>, U1</ins>&gt;,
                                         <i>synth-three-way-result</i>&lt;T2<ins>, U2</ins>&gt;&gt;
    operator&lt;=&gt;(const pair&lt;T1, T2&gt;&amp;, const pair&lt;<del>T</del><ins>U</ins>1, <del>T</del><ins>U</ins>2&gt;&amp;);
[&hellip;]
</pre>
</blockquote>
</li>

<li><p>Modify 22.3.3 <a href="https://wg21.link/pairs.spec">[pairs.spec]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class T1, class T2<ins>, class U1, class U2</ins>&gt;
  constexpr bool operator==(const pair&lt;T1, T2&gt;&amp; x, const pair&lt;<del>T</del><ins>U</ins>1, <del>T</del><ins>U</ins>2&gt;&amp; y);
</pre>
<blockquote>
<p>
-1- [&hellip;]
<p/>
-2- [&hellip;]
</p>
</blockquote>
<pre>
template&lt;class T1, class T2<ins>, class U1, class U2</ins>&gt;
  constexpr common_comparison_category_t&lt;<i>synth-three-way-result</i>&lt;T1<ins>, U1</ins>&gt;,
                                         <i>synth-three-way-result</i>&lt;T2<ins>, U2</ins>&gt;&gt;
    operator&lt;=&gt;(const pair&lt;T1, T2&gt;&amp; x, const pair&lt;<del>T</del><ins>U</ins>1, <del>T</del><ins>U</ins>2&gt;&amp; y);
</pre>
<blockquote>
<p>
-3- [&hellip;]
</p>
</blockquote>
</blockquote>
</li>

</ol>





<hr>
<h3><a name="3869" href="https://cplusplus.github.io/LWG/lwg-active.html#3869">3869</a>. Deprecate <tt>std::errc</tt> constants related to UNIX STREAMS</h3>
<p><b>Section:</b> 19.5.2 <a href="https://wg21.link/system.error.syn">[system.error.syn]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Jonathan Wakely <b>Opened:</b> 2023-01-30 <b>Last modified:</b> 2023-02-07</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#system.error.syn">issues</a> in [system.error.syn].</p>
<p><b>Discussion:</b></p>
<p>
This is the resolution for NB comment <b><a href="https://github.com/cplusplus/nbballot/issues/444">GB-084</a></b>
</p>
<p>
The error numbers
<tt>ENODATA</tt>, <tt>ENOSR</tt>, <tt>ENOSTR</tt> and <tt>ETIME</tt>
are all marked "obsolecent" in POSIX 2017 (the current normative reference for C++)
and they are absent in the current POSIX 202x draft.
They related to the obsolete STREAMS API,
which was optional and not required for conformance to the previous POSIX standard
(because popular unix-like systems refused to implement it).
C++11 added those error numbers to <tt>&lt;errno.h&gt;</tt>
and also defined corresponding <tt>errc</tt> enumerators:
<tt>errc::no_message_available</tt>,
<tt>errc::no_stream_resources</tt>,
<tt>errc::not_a_stream</tt> and
<tt>errc::stream_timeout</tt>.
</p>
<p>
Given the obsolescent status of those constants in the current normative reference
and their absence from the next POSIX standard, WG21 should consider deprecating them now.
A deprecation period will allow removing them when C++ is eventually rebased to a new POSIX standard.
Otherwise C++ will be left with dangling references to
<tt>ENODATA</tt>, <tt>ENOSR</tt>, <tt>ENOSTR</tt> and <tt>ETIME</tt>
that are not defined in the POSIX reference.
</p>
<p>
After a period of deprecation they can be removed from Annex D,
and the names added to 16.4.5.3.2 <a href="https://wg21.link/zombie.names">[zombie.names]</a> so that implementations
can continue to define them if they need to.
</p>

<p><i>[Issaquah 2023-02-06; LWG]</i></p>

<p>Unanimous consent (9/0/0) to move to Immediate for C++23.</p>



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

<ol>
<li><p>Modify 19.4.2 <a href="https://wg21.link/cerrno.syn">[cerrno.syn]</a>, header <tt>&lt;cerrno&gt;</tt> synopsis, as indicated:</p>

<blockquote>
<pre><code>
  #define ENETUNREACH <i>see below</i>
  #define ENFILE <i>see below</i>
  #define ENOBUFS <i>see below</i>
  <del>#define ENODATA <i>see below</i></del>
  #define ENODEV <i>see below</i>
  #define ENOENT <i>see below</i>
  #define ENOEXEC <i>see below</i>
  #define ENOLCK <i>see below</i>
  #define ENOLINK <i>see below</i>
  #define ENOMEM <i>see below</i>
  #define ENOMSG <i>see below</i>
  #define ENOPROTOOPT <i>see below</i>
  #define ENOSPC <i>see below</i>
  <del>#define ENOSR <i>see below</i></del>
  <del>#define ENOSTR <i>see below</i></del>
  #define ENOSYS <i>see below</i>
  #define ENOTCONN <i>see below</i>
  #define ENOTDIR <i>see below</i>
  #define ENOTEMPTY <i>see below</i>
  ...
  #define EROFS <i>see below</i>
  #define ESPIPE <i>see below</i>
  #define ESRCH <i>see below</i>
  <del>#define ETIME <i>see below</i></del>
  #define ETIMEDOUT <i>see below</i>
  #define ETXTBSY <i>see below</i>
  #define EWOULDBLOCK <i>see below</i>
  #define EXDEV <i>see below</i>
</code></pre>
<p>-1- The meaning of the macros in this header is defined by the POSIX standard.</p>
</blockquote>
</li>

<li><p>Modify 19.5.2 <a href="https://wg21.link/system.error.syn">[system.error.syn]</a>, header <tt>&lt;system_error&gt;</tt> synopsis, as indicated:</p>

<blockquote>
<pre><code>
    no_child_process,                   // ECHILD
    no_link,                            // ENOLINK
    no_lock_available,                  // ENOLCK
    <del>no_message_available,               // ENODATA</del>
    no_message,                         // ENOMSG
    no_protocol_option,                 // ENOPROTOOPT
    no_space_on_device,                 // ENOSPC
    <del>no_stream_resources,                // ENOSR</del>
    no_such_device_or_address,          // ENXIO
    no_such_device,                     // ENODEV
    no_such_file_or_directory,          // ENOENT
    no_such_process,                    // ESRCH
    not_a_directory,                    // ENOTDIR
    not_a_socket,                       // ENOTSOCK
    <del>not_a_stream,                       // ENOSTR</del>
    not_connected,                      // ENOTCONN
    not_enough_memory,                  // ENOMEM
    ...
    result_out_of_range,                // ERANGE
    state_not_recoverable,              // ENOTRECOVERABLE
    <del>stream_timeout,                     // ETIME</del>
    text_file_busy,                     // ETXTBSY
    timed_out,                          // ETIMEDOUT
</code></pre>
</blockquote>
</li>

<li>
<p>
Modify D <a href="https://wg21.link/depr">[depr]</a>, Annex D, Compatibility Features, by adding a new subclause
before D.13 <a href="https://wg21.link/depr.default.allocator">[depr.default.allocator]</a>:
:</p>

<blockquote>
<p><ins><b>D.?? Deprecated error numbers [depr.cerrno]</b></ins></p>
<p><ins>
-1- The following macros are defined in addition to those specified in
19.4.2 <a href="https://wg21.link/cerrno.syn">[cerrno.syn]</a>:
</ins></p>

<pre><code>
  <ins>#define ENODATA <i>see below</i></ins>
  <ins>#define ENOSR <i>see below</i></ins>
  <ins>#define ENOSTR <i>see below</i></ins>
  <ins>#define ETIME <i>see below</i></ins>
</code></pre>
<p><ins>-2- The meaning of these macros is defined by the POSIX standard.</ins></p>

<p><ins>
-4- The following <tt>enum errc</tt> enumerators are defined
in addition to those specified in 19.5.2 <a href="https://wg21.link/system.error.syn">[system.error.syn]</a>:
</ins></p>

<pre><code>
  <ins>no_message_available,               // ENODATA</ins>
  <ins>no_stream_resources,                // ENOSR</ins>
  <ins>not_a_stream,                       // ENOSTR</ins>
  <ins>stream_timeout,                     // ETIME</ins>
</code></pre>

<p><ins>
-4-
The value of each <tt>enum errc</tt> enumerator above
is the same as the value of the <tt>&lt;cerrno&gt;</tt> macro shown in the above synopsis.
</ins></p>
</blockquote>
</li>
</ol>






<hr>
<h3><a name="3870" href="https://cplusplus.github.io/LWG/lwg-active.html#3870">3870</a>. Remove <tt><i>voidify</i></tt></h3>
<p><b>Section:</b> 27.11.1 <a href="https://wg21.link/specialized.algorithms.general">[specialized.algorithms.general]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Jonathan Wakely <b>Opened:</b> 2023-01-30 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
This is the resolution for NB comment <b><a href="https://github.com/cplusplus/nbballot/issues/452">GB-121</a></b>
</p>

<p>
The <tt><i>voidify</i></tt> helper breaks const-correctness, for no tangible benefit.
C++20 ballot comment US 215 also suggested removing it,
but failed to achieve consensus. That should be reconsidered.
</p>
<p>
The only claimed benefits are:
<ul>
<li>Allowing the <tt>uninitialized_xxx</tt> algorithms
to create objects in const storage
(including overwriting objects declared as const which is usually UB).
The caller should be responsible for using <tt>const_cast</tt>
if that's really desirable.
Implicitly removing 'const' is unsafe and unnecessary.
</li>
<li>
Supporting creation of const objects with <tt>std::construct_at</tt>.
This seems reasonable, but should be supported by adding a dedicated
function that doesn't conflate the type of the storage to write to
and the object to create, e.g. <tt>construct_at&lt;const T&gt;(ptr)</tt>.
</li>
</ul>
</p>

<p><i>[Issaquah 2023-02-06; LWG]</i></p>

<p>
Casey noted:
</p>
<blockquote>
The claimed benefit is allowing the <tt>uninitialized_xxx</tt> algorithms
to create objects of const and/or volatile type, which they cannot otherwise do
since they deduce the type of object to be created from the reference type
of the pertinent iterator. Creating const objects has some (marginal?) benefits
over using const pointers to mutable objects. For example, their non-mutable
members cannot be modified via casting away const without undefined behavior.
A unit test might take advantage of this behavior to force a compiler to
diagnose such undefined behavior in a constant expression.
</blockquote>
<p>
The issue submitter was aware of this, but an open Core issue,
CWG <a href="https://cplusplus.github.io/CWG/issues/2514.html">2514</a>,
would invalidate that benefit. If accepted, objects with dynamic storage
duration (such as those created by <tt>std::construct_as</tt> and the
<tt>std::uninitialized_xxx</tt> algorithms) would never be const objects,
so casting away the const would not be undefined. So implicitly removing
const in <tt><i>voidify</i></tt> would still allowing modifying "truly const"
objects (resulting in undefined behaviour), without being able to create
"truly const" objects in locations where that actually <i>is</i> safe.
If CWG 2514 is accepted, the <tt><i>voidify</i></tt> behaviour would be all
downside.
</p>
<p>
LWG requested removing the remaining casts from the proposed resolution,
relying on an implicit conversion to <tt>void*</tt> instead.
Move to Immediate for C++23.
</p>

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

<ol>
<li><p>Modify 27.11.1 <a href="https://wg21.link/specialized.algorithms.general">[specialized.algorithms.general]</a>, <b>General</b>,
as indicated:</p>

<blockquote>
<p>-4-
Some algorithms specified in 27.11 <a href="https://wg21.link/specialized.algorithms">[specialized.algorithms]</a>
make use of the exposition-only function <tt><i>voidify</i></tt>:
</p>
<blockquote>
<pre><code>
template&lt;class T&gt;
  constexpr void* <i>voidify</i>(T&amp; obj) noexcept {
    return <del>const_cast&lt;void*&gt;(</del>static_cast&lt;<del>const volatile </del>void*&gt;(addressof(obj))<del>)</del>;
  }
</code></pre>
</blockquote>
</blockquote>
</li>
</ol>

</blockquote>



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

<ol>
<li><p>Modify 27.11.1 <a href="https://wg21.link/specialized.algorithms.general">[specialized.algorithms.general]</a>, <b>General</b>,
as indicated:</p>

<blockquote>
<p>-4-
Some algorithms specified in 27.11 <a href="https://wg21.link/specialized.algorithms">[specialized.algorithms]</a>
make use of the exposition-only function <tt><i>voidify</i></tt>:
</p>
<blockquote>
<pre><code>
template&lt;class T&gt;
  constexpr void* <i>voidify</i>(T&amp; obj) noexcept {
    return <del>const_cast&lt;void*&gt;(static_cast&lt;const volatile void*&gt;(</del>addressof(obj)<del>))</del>;
  }
</code></pre>
</blockquote>
</blockquote>
</li>
</ol>






<hr>
<h3><a name="3871" href="https://cplusplus.github.io/LWG/lwg-active.html#3871">3871</a>. Adjust note about <tt>terminate</tt></h3>
<p><b>Section:</b> 16.4.2.5 <a href="https://wg21.link/compliance">[compliance]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> CA <b>Opened:</b> 2023-02-01 <b>Last modified:</b> 2023-02-07</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#compliance">issues</a> in [compliance].</p>
<p><b>Discussion:</b></p>
<p>
This is the resolution for NB comment <b><a href="https://github.com/cplusplus/nbballot/issues/463">CA-076</a></b>
</p>
<p>
16.4.2.5 <a href="https://wg21.link/compliance">[compliance]</a> p4 has this note:
</p>
<blockquote>
[<i>Note 1</i>: Throwing a standard library provided exception is not
observably different from <tt>terminate()</tt> if the implementation
does not unwind the stack during exception handling
(14.4 <a href="https://wg21.link/except.handle">[except.handle]</a>)
and the user's program contains no catch blocks. &mdash; <i>end note</i>]
</blockquote>
<p>
Even under the conditions described by the note, a call to <tt>terminate()</tt>
is observably different from throwing an exception if the current
<tt>terminate_handler</tt> function observes what would have been
the currently handled exception in the case where the exception was thrown.
</p>
<p>
The set of conditions should be extended to include something along the lines of
"and the current <tt>terminate_handler</tt> function simply calls <tt>abort()</tt>".
</p>
<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">

<p>
This wording is relative to <a href="https://wg21.link/N4928">N4928</a>.
</p>

<ol>
<li>
<p>
Modify 16.4.2.5 <a href="https://wg21.link/compliance">[compliance]</a>, "Freestanding implementations", as indicated:
</p>

<blockquote>
-4-
[<i>Note 1</i>: Throwing a standard library provided exception is not
observably different from <tt>terminate()</tt> if the implementation
does not unwind the stack during exception handling
(14.4 <a href="https://wg21.link/except.handle">[except.handle]</a>)
and the user's program contains no catch blocks
<ins>and the current <tt>terminate_handler</tt> function simply calls
<tt>abort()</tt></ins>.
&mdash; <i>end note</i>]
</blockquote>
</li>
</ol>

</blockquote>

<p><i>[Issaquah 2023-02-06; LWG]</i></p>

<p>If the note isn't true then remove it.<br/>
Poll: keep note and change as proposed? 3/1/10.<br/>
Poll: drop the note entirely? 10/0/5.<br/>
Drop the note and move to Immediate for C++20: 9/0/2.
</p>


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

<ol>
<li>
<p>
Modify 16.4.2.5 <a href="https://wg21.link/compliance">[compliance]</a>, "Freestanding implementations", as indicated:
</p>

<blockquote>
<del>
-4-
[<i>Note 1</i>: Throwing a standard library provided exception is not
observably different from <tt>terminate()</tt> if the implementation
does not unwind the stack during exception handling
(14.4 <a href="https://wg21.link/except.handle">[except.handle]</a>)
and the user's program contains no catch blocks.
&mdash; <i>end note</i>]
</del>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3872" href="https://cplusplus.github.io/LWG/lwg-active.html#3872">3872</a>. <tt>basic_const_iterator</tt> should have custom <tt>iter_move</tt></h3>
<p><b>Section:</b> 25.5.3 <a href="https://wg21.link/const.iterators">[const.iterators]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2023-01-31 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>3
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#const.iterators">active issues</a> in [const.iterators].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#const.iterators">issues</a> in [const.iterators].</p>
<p><b>Discussion:</b></p>
<p>
The standard does not currently customize <tt>iter_move</tt> for <tt>basic_const_iterator</tt>, 
which means that applying <tt>iter_move</tt> to <tt>basic_const_iterator</tt> will invoke the default behavior.
Although the intent of such an operation is unpredictable, it does introduce some inconsistencies:
</p>
<blockquote><pre>
int x[] = {1, 2, 3};
using R1 = decltype(           x  | views::as_rvalue | views::as_const);
using R2 = decltype(           x  | views::as_const  | views::as_rvalue);
using Z1 = decltype(views::zip(x) | views::as_rvalue | views::as_const);
using Z2 = decltype(views::zip(x) | views::as_const  | views::as_rvalue);

static_assert(same_as&lt;ranges::range_reference_t&lt;R1&gt;,       const int&amp;&amp;&gt;);
static_assert(same_as&lt;ranges::range_reference_t&lt;R2&gt;,       const int&amp;&amp;&gt;);
static_assert(same_as&lt;ranges::range_reference_t&lt;Z1&gt;, tuple&lt;const int&amp;&amp;&gt;&gt;);
static_assert(same_as&lt;ranges::range_reference_t&lt;Z2&gt;, tuple&lt;const int&amp;&amp;&gt;&gt;); // <span style="color:red;font-weight:bolder">failed</span>
</pre></blockquote>
<p>
In the above example, <tt>views::zip(x) | views::as_const</tt> will produce a range whose iterator type is 
<tt>basic_const_iterator</tt> with reference of <tt>tuple&lt;const int&amp;&gt;</tt>.
Since <tt>iter_move</tt> adopts the default behavior, its rvalue reference will also be 
<tt>tuple&lt;const int&amp;&gt;</tt>, so applying <tt>views::as_rvalue</tt> to it won't have any effect.
<p/>
Such an inconsistency seems undesirable.
<p/>
The proposed resolution adds an <tt>iter_move</tt> specialization for <tt>basic_const_iterator</tt> and specifies 
the return type as 
<tt>common_reference_t&lt;const iter_value_t&lt;It&gt;&amp;&amp;, iter_rvalue_reference_t&lt;It&gt;&gt;</tt>, 
which is the type that <tt>input_iterator</tt> is guaranteed to be valid. This is also in sync with the behavior 
of range-v3.
</p>

<p><i>[Issaquah 2023-02-10; LWG issue processing]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>
<li>
<p>Modify 25.5.3 <a href="https://wg21.link/const.iterators">[const.iterators]</a> as indicated:</p>

<blockquote>
<pre>
namespace std {
  template&lt;class I&gt;
    concept <i>not-a-const-iterator</i> = <i>see below</i>;

<ins>  template&lt;indirectly_readable I&gt;
    using <i>iter-const-rvalue-reference-t</i> =  // <i>exposition only</i>
      common_reference_t&lt;const iter_value_t&lt;I&gt;&amp;&amp;, iter_rvalue_reference_t&lt;I&gt;&gt;;</ins>

  template&lt;input_iterator Iterator&gt;
  class basic_const_iterator {
    Iterator <i>current_</i> = Iterator();                             // <i>exposition only</i>
    using <i>reference</i> = iter_const_reference_t&lt;Iterator&gt;;         // <i>exposition only</i>
    <ins>using <i>rvalue-reference</i> = <i>iter-const-rvalue-reference-t</i>&lt;Iterator&gt;;  // <i>exposition only</i></ins>

  public:
    [&hellip;]
    template&lt;sized_sentinel_for&lt;Iterator&gt; S&gt;
      requires different-from&lt;S, basic_const_iterator&gt;
      friend constexpr difference_type operator-(const S&amp; x, const basic_const_iterator&amp; y);
      <ins>friend constexpr <i>rvalue-reference</i> iter_move(const basic_const_iterator&amp; i)
        noexcept(noexcept(static_cast&lt;<i>rvalue-reference</i>&gt;(ranges::iter_move(i.<i>current_</i>)))) 
      {
        return static_cast&lt;<i>rvalue-reference</i>&gt;(ranges::iter_move(i.<i>current_</i>));
      }</ins>
  };
}
</pre>
</blockquote>
</li>
</ol>






<hr>
<h3><a name="3875" href="https://cplusplus.github.io/LWG/lwg-active.html#3875">3875</a>. <tt>std::ranges::repeat_view&lt;T, IntegerClass&gt;::<i>iterator</i></tt> may be ill-formed</h3>
<p><b>Section:</b> 26.6.5 <a href="https://wg21.link/range.repeat">[range.repeat]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Jiang An <b>Opened:</b> 2023-02-05 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
26.6.5.3 <a href="https://wg21.link/range.repeat.iterator">[range.repeat.iterator]</a> specifies <tt>difference_type</tt> as
</p>
<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;">
<pre>
using difference_type = conditional_t&lt;<i>is-signed-integer-like</i>&lt;<i>index-type</i>&gt;,
  <i>index-type</i>,
  <i>IOTA-DIFF-T</i>(<i>index-type</i>)&gt;;
</pre>
</blockquote>
<p>
which always instantiates <tt><i>IOTA-DIFF-T</i>(<i>index-type</i>)</tt>, and thus possibly makes the program ill-formed when 
<tt>index-type</tt> is an integer-class type (<tt><i>index-type</i></tt> is same as <tt>Bound</tt> in this case), because 
<tt><i>IOTA-DIFF-T</i>(<i>index-type</i>)</tt> is specified to be <tt>iter_difference_t&lt;<i>index-type</i>&gt;</tt> 
which may be ill-formed (26.6.4.2 <a href="https://wg21.link/range.iota.view">[range.iota.view]</a>/1.1).
<p/>
I think the intent is using <tt><i>index-type</i></tt> as-is without instantiating <tt><i>IOTA-DIFF-T</i></tt> when 
<tt><i>is-signed-integer-like</i>&lt;<i>index-type</i>&gt;</tt> is <tt>true</tt>.
<p/>
However, when <tt>Bound</tt> is an unsigned integer-class type, it's unclear which type should the difference type be, 
or whether <tt>repeat_view</tt> should be well-formed when the possibly intended <tt><i>IOTA-DIFF-T</i>(Bound)</tt> is ill-formed.
</p>
<p><i>[2023-02-09 Tim adds wording]</i></p>

<p>We should reject types for which there is no usable difference type.</p>

<p><i>[Issaquah 2023-02-09; LWG]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>
<li><p>Modify 26.2 <a href="https://wg21.link/ranges.syn">[ranges.syn]</a>, header <tt>&lt;ranges&gt;</tt> synopsis, as indicated:</p>
<blockquote>
<pre>
// [&hellip;]
namespace std::ranges {
  template&lt;move_constructible W, semiregular Bound = unreachable_sentinel_t&gt;
    requires <ins><i>see below</i></ins><del>(is_object_v&lt;W> &amp;&amp; same_as&lt;W, remove_cv_t&lt;W&gt;&gt; &amp;&amp;
              (<i>is-integer-like</i>&lt;Bound> || same_as&lt;Bound, unreachable_sentinel_t&gt;))</del>
  class repeat_view;
</pre>
</blockquote>
</li>

<li><p>Modify 26.6.5.2 <a href="https://wg21.link/range.repeat.view">[range.repeat.view]</a> as indicated:</p>
<blockquote>
<pre>
namespace std::ranges {
  
<ins>  template&lt;class T&gt;
  concept <i>integer-like-with-usable-difference-type</i> =   //<i>exposition only</i>
    <i>is-signed-integer-like</i>&lt;T> || (<i>is-integer-like</i>&lt;T> &amp;&amp; weakly_incrementable&lt;T>);</ins>

  template&lt;move_constructible W, semiregular Bound = unreachable_sentinel_t&gt;
    requires (is_object_v&lt;W> &amp;&amp; same_as&lt;W, remove_cv_t&lt;W&gt;&gt; &amp;&amp;
              (<i><del>is-integer-like</del><ins>integer-like-with-usable-difference-type</ins></i>&lt;Bound> || same_as&lt;Bound, unreachable_sentinel_t&gt;))
  class repeat_view {
    [&hellip;]
  };
}
</pre>
</blockquote>
</li>

<li><p>Modify 26.6.5.3 <a href="https://wg21.link/range.repeat.iterator">[range.repeat.iterator]</a> as indicated:</p>
<blockquote>
<pre>
namespace std::ranges {
  template&lt;move_constructible W, semiregular Bound<del> = unreachable_sentinel_t</del>&gt;
    requires (is_object_v&lt;W> &amp;&amp; same_as&lt;W, remove_cv_t&lt;W&gt;&gt; &amp;&amp;
              (<i><del>is-integer-like</del><ins>integer-like-with-usable-difference-type</ins></i>&lt;Bound> || same_as&lt;Bound, unreachable_sentinel_t&gt;))
  class repeat_view&lt;W, Bound>::<i>iterator</i> {
  private:
    using <i>index-type</i> =                  <i>// exposition only</i>
      conditional_t&lt;same_as&lt;Bound, unreachable_sentinel_t&gt;, ptrdiff_t, Bound&gt;;
    [&hellip;]
  public:
    [&hellip;]
    using difference_type = <ins><i>see below</i></ins><del>conditional_t&lt;<i>is-signed-integer-like</i>&lt;<i>index-type</i>&gt;,
        <i>index-type</i>,
        <i>IOTA-DIFF-T</i>(<i>index-type</i>)></del>;
    [&hellip;]
  };
}
</pre>
</blockquote>
<p>
<ins>-?- If <tt><i>is-signed-integer-like</i>&lt;<i>index-type</i>&gt;</tt> is <tt>true</tt>,
the member <i>typedef-name</i> <tt>difference_type</tt> denotes <tt><i>index-type</i></tt>.
Otherwise, it denotes <tt><i>IOTA-DIFF-T</i>(<i>index-type</i>)</tt> 
(26.6.4.2 <a href="https://wg21.link/range.iota.view">[range.iota.view]</a>).</ins>
</p>
</li>
</ol>






<hr>
<h3><a name="3876" href="https://cplusplus.github.io/LWG/lwg-active.html#3876">3876</a>. Default constructor of <tt>std::layout_<i>XX</i>::mapping</tt> misses precondition</h3>
<p><b>Section:</b> 24.7.3.4 <a href="https://wg21.link/mdspan.layout">[mdspan.layout]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Christian Trott <b>Opened:</b> 2023-02-09 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
As shortly discussed during the LWG review of a <tt>layout_stride</tt> defect, there is currently no protection against 
creating layout mappings with all static extents where the product of those extents exceeds the representable 
value range of the <tt>index_type</tt>.
<p/>
For example, the following statement does not violate any preconditions or mandates:
</p>
<blockquote><pre>
layout_left::mapping&lt;extents&lt;int, 100000, 100000&gt;&gt; a{};
</pre></blockquote>
<p>
But <tt>a.required_span_size()</tt> would overflow since the implied span size is 10B and thus exceeds what 
<tt>int</tt> can represent.
<p/>
This is only a problem for all static extents, since with any dynamic extent in the mix the implied span size is <tt>0</tt>. 
Hence we can check for this via a mandates check on the class.
<p/>
The paper <a href="https://wg21.link/P2798R0">P2798R0</a> has been provided with the proposed wording as shown below.
</p>

<p><i>[Issaquah 2023-02-10; LWG issue processing]</i></p>

<p>Move to Immediate for C++23</p>


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

<ol>
<li><p>Modify 24.7.3.4.5.1 <a href="https://wg21.link/mdspan.layout.left.overview">[mdspan.layout.left.overview]</a> as indicated:</p>
<blockquote>
<p>
-2- If <tt>Extents</tt> is not a specialization of <tt>extents</tt>, then the program is ill-formed.
<p/>
-3- <tt>layout_left::mapping&lt;E&gt;</tt> is a trivially copyable type that models <tt>regular</tt> for each <tt>E</tt>.
<p/>
<ins>-?- <i>Mandates</i>: If <tt>Extents::rank_dynamic() == 0</tt> is <tt>true</tt>, then the size of the multidimensional 
index space <tt>Extents()</tt> is representable as a value of type <tt>typename Extents::index_type</tt>.</ins>
</p>
</blockquote>
</li>

<li><p>Modify 24.7.3.4.6.1 <a href="https://wg21.link/mdspan.layout.right.overview">[mdspan.layout.right.overview]</a> as indicated:</p>
<blockquote>
<p>
-2- If <tt>Extents</tt> is not a specialization of <tt>extents</tt>, then the program is ill-formed.
<p/>
-3- <tt>layout_right::mapping&lt;E&gt;</tt> is a trivially copyable type that models <tt>regular</tt> for each <tt>E</tt>.
<p/>
<ins>-?- <i>Mandates</i>: If <tt>Extents::rank_dynamic() == 0</tt> is <tt>true</tt>, then the size of the multidimensional 
index space <tt>Extents()</tt> is representable as a value of type <tt>typename Extents::index_type</tt>.</ins>
</p>
</blockquote>
</li>

<li><p>Modify 24.7.3.4.7.1 <a href="https://wg21.link/mdspan.layout.stride.overview">[mdspan.layout.stride.overview]</a> as indicated:</p>
<blockquote>
<p>
-2- If <tt>Extents</tt> is not a specialization of <tt>extents</tt>, then the program is ill-formed.
<p/>
-3- <tt>layout_stride::mapping&lt;E&gt;</tt> is a trivially copyable type that models <tt>regular</tt> for each <tt>E</tt>.
<p/>
<ins>-?- <i>Mandates</i>: If <tt>Extents::rank_dynamic() == 0</tt> is <tt>true</tt>, then the size of the multidimensional 
index space <tt>Extents()</tt> is representable as a value of type <tt>typename Extents::index_type</tt>.</ins>
</p>
</blockquote>
</li>
</ol>






<hr>
<h3><a name="3877" href="https://cplusplus.github.io/LWG/lwg-active.html#3877">3877</a>. Incorrect constraints on <tt>const</tt>-qualified monadic overloads for <tt>std::expected</tt></h3>
<p><b>Section:</b> 22.8.6.7 <a href="https://wg21.link/expected.object.monadic">[expected.object.monadic]</a>, 22.8.7.7 <a href="https://wg21.link/expected.void.monadic">[expected.void.monadic]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Sy Brand <b>Opened:</b> 2023-02-09 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#expected.object.monadic">active issues</a> in [expected.object.monadic].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#expected.object.monadic">issues</a> in [expected.object.monadic].</p>
<p><b>Discussion:</b></p>
<p>
The constraints for <tt>and_then</tt>, <tt>transform</tt>, <tt>transform_error</tt>, and <tt>or_else</tt> 
for <tt>std::expected</tt> seem incorrect for <tt>const</tt> overloads. E.g., from 22.8.6.7 <a href="https://wg21.link/expected.object.monadic">[expected.object.monadic]</a>
</p>
<blockquote><pre>
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const &amp;&amp;;
[&hellip;]
</pre>
<blockquote>
<p>
<i>Constraints</i>: <tt>is_move_constructible_v&lt;E&gt;</tt> is <tt>true</tt>.
</p>
</blockquote>
</blockquote>
<p>
That constraint should likely be <tt>is_move_constructible_v&lt;const E&gt;</tt> for the <tt>const</tt>-qualified version. 
Same for the lvalue overloads, and for the three other functions, including in the <tt>void</tt> partial specialization. 
For example, currently this code would result in a hard compiler error inside the body of <tt>transform</tt> rather than 
failing the constraint:
</p>
<blockquote><pre>
const std::expected&lt;int, std::unique_ptr&lt;int&gt;&gt; e;
std::move(e).transform([](auto) { return 42; });
</pre></blockquote>
<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">
<p>
This wording is relative to <a href="https://wg21.link/N4928">N4928</a>.
</p>

<ol>
<li><p>Modify 22.8.6.7 <a href="https://wg21.link/expected.object.monadic">[expected.object.monadic]</a> as indicated:</p>
<blockquote>
<pre>
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-2- <i>Constraints</i>: <tt>is_copy_constructible_v&lt;<del>E</del><ins>decltype((error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-6- <i>Constraints</i>: <tt>is_move_constructible_v&lt;<del>E</del><ins>decltype((error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-10- <i>Constraints</i>: <tt>is_copy_constructible_v&lt;<del>T</del><ins>decltype((value()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-14- <i>Constraints</i>: <tt>is_move_constructible_v&lt;<del>T</del><ins>decltype((value()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-18- <i>Constraints</i>: <tt>is_copy_constructible_v&lt;<del>E</del><ins>decltype((error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-22- <i>Constraints</i>: <tt>is_move_constructible_v&lt;<del>E</del><ins>decltype((error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-26- <i>Constraints</i>: <tt>is_copy_constructible_v&lt;<del>T</del><ins>decltype((value()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-30- <i>Constraints</i>: <tt>is_move_constructible_v&lt;<del>T</del><ins>decltype((value()))</ins>&gt;</tt> is <tt>true</tt>.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 22.8.7.7 <a href="https://wg21.link/expected.void.monadic">[expected.void.monadic]</a> as indicated:</p>
<blockquote>
<pre>
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-2- <i>Constraints</i>: <tt>is_copy_constructible_v&lt;<del>E</del><ins>decltype((error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-6- <i>Constraints</i>: <tt>is_move_constructible_v&lt;<del>E</del><ins>decltype((error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-16- <i>Constraints</i>: <tt>is_copy_constructible_v&lt;<del>E</del><ins>decltype((error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-20- <i>Constraints</i>: <tt>is_move_constructible_v&lt;<del>E</del><ins>decltype((error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>

</blockquote>
</li>
</ol>

</blockquote>

<p><i>[Issaquah 2023-02-09; Jonathan provides improved wording]</i></p>

<p><i>[Issaquah 2023-02-09; LWG]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>
<li><p>Modify 22.8.6.7 <a href="https://wg21.link/expected.object.monadic">[expected.object.monadic]</a> as indicated:</p>
<blockquote>
<pre>
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-2- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;E<ins>, decltype(error())</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-6- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;E<ins>, decltype(std::move(error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-10- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;T<ins>, decltype(value())</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto or_else(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-14- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;T<ins>, decltype(std::move(value()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-18- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;E<ins>, decltype(error())</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-22- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;E<ins>, decltype(std::move(error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-26- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;T<ins>, decltype(value())</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto transform_error(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-30- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;T<ins>, decltype(std::move(value()))</ins>&gt;</tt> is <tt>true</tt>.
</p>
</blockquote>
</blockquote>
</li>

<li><p>Modify 22.8.7.7 <a href="https://wg21.link/expected.void.monadic">[expected.void.monadic]</a> as indicated:</p>
<blockquote>
<pre>
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-2- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;E<ins>, decltype(error())</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto and_then(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-6- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;E<ins>, decltype(std::move(error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;;
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const &amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-16- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;E<ins>, decltype(error())</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>
<pre>
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) &amp;&amp;;
template&lt;class F&gt; constexpr auto transform(F&amp;&amp; f) const &amp;&amp;;
</pre>
<blockquote>
<p>
[&hellip;]
<p/>
-20- <i>Constraints</i>: <tt>is_<del>copy_</del>constructible_v&lt;E<ins>, decltype(std::move(error()))</ins>&gt;</tt> is <tt>true</tt>.
<p/>
[&hellip;]
</p>
</blockquote>

</blockquote>
</li>
</ol>






<hr>
<h3><a name="3878" href="https://cplusplus.github.io/LWG/lwg-active.html#3878">3878</a>. <tt>import std;</tt> should guarantee initialization of standard iostreams objects</h3>
<p><b>Section:</b> 31.4.2 <a href="https://wg21.link/iostream.objects.overview">[iostream.objects.overview]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Tim Song <b>Opened:</b> 2023-02-09 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
In the old world, <tt>#include &lt;iostream></tt>
behaves as if it defined a static-storage-duration <tt>ios_base::Init</tt> object, 
which causes the standard iostreams objects to be initialized (if necessary)
on startup and flushed on shutdown.
<p/>
But we don't include headers with <tt>import std;</tt>, so we need separate wording to
provide this guarantee. The proposed resolution below was adapted from a suggestion by 
Mathias Stearn on the reflector.
</p>
<p><i>[2023-02-09 Tim updates wording following LWG discussion]</i></p>


<p><i>[Issaquah 2023-02-09; LWG]</i></p>

<p>Move to Immediate for C++23</p>



<p id="res-3878"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4928">N4928</a>.
</p>
<ol>
<li><p>Modify 31.4.2 <a href="https://wg21.link/iostream.objects.overview">[iostream.objects.overview]</a>p5  as indicated:</p>
<p>
-5- The results of including <tt>&lt;iostream></tt> in a translation unit shall be 
as if <tt>&lt;iostream></tt> defined an instance of <tt>ios_base::Init</tt> with static
storage duration. <ins>Each C++ library module (16.4.2.4 <a href="https://wg21.link/std.modules">[std.modules]</a>)
in a hosted implementation shall behave as if it contains an interface unit that defines
an unexported <tt>ios_base::Init</tt> variable with ordered initialization 
(6.9.3.3 <a href="https://wg21.link/basic.start.dynamic">[basic.start.dynamic]</a>). </ins>
<p/>
<ins>[<i>Note ?:</i> As a result, the definition of that variable is appearance-ordered
before any declaration following the point of importation of a C++ library module. 
Whether such a definition exists is unobservable by a program that does not reference
any of the standard iostream objects. &mdash; <i>end note</i>]</ins>
</p>
</li>
</ol>





<hr>
<h3><a name="3879" href="https://cplusplus.github.io/LWG/lwg-active.html#3879">3879</a>. <tt>erase_if</tt> for <tt>flat_{,multi}set</tt> is incorrectly specified</h3>
<p><b>Section:</b> 24.6.11.5 <a href="https://wg21.link/flat.set.erasure">[flat.set.erasure]</a>, 24.6.12.5 <a href="https://wg21.link/flat.multiset.erasure">[flat.multiset.erasure]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Tim Song <b>Opened:</b> 2023-02-09 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
The current specification of <tt>erase_if</tt> for <tt>flat_{,multi}set</tt>
calls <tt>ranges::remove_if</tt> on the set, which is obviously incorrect &mdash;
the set only present constant views of its elements.
</p>

<p><i>[Issaquah 2023-02-09; LWG]</i></p>

<p>Move to Immediate for C++23</p>



<p id="res-3879"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4928">N4928</a>.
</p>
<ol>
<li><p>Modify 24.6.11.5 <a href="https://wg21.link/flat.set.erasure">[flat.set.erasure]</a> as indicated:</p>
<blockquote>
<pre>
template&lt;class Key, class Compare, class KeyContainer, class Predicate&gt;
  typename flat_set&lt;Key, Compare, KeyContainer&gt;::size_type
    erase_if(flat_set&lt;Key, Compare, KeyContainer&gt;&amp; c, Predicate pred);
</pre>
<blockquote>
<p>
<del>-1- <i>Effects:</i> Equivalent to:</del>
</p>
<blockquote>
<pre>
<del>auto [erase_first, erase_last] = ranges::remove_if(c, pred);
auto n = erase_last - erase_first;
c.erase(erase_first, erase_last);
return n;</del>
</pre>
</blockquote>
<p>
<ins>
-1- <i>Preconditions:</i> <tt>Key</tt> meets the <i>Cpp17MoveAssignable</i> requirements.
</ins>
<p/>
<ins>
-2- <i>Effects:</i> Let <i>E</i> be <tt>bool(pred(as_const(e)))</tt>. 
Erases all elements <tt>e</tt> in <tt>c</tt> for which <i>E</i> holds.
</ins>
<p/>
<ins>-3- <i>Returns:</i> The number of elements erased.</ins>
<p/>
<ins>-4- <i>Complexity:</i> Exactly <tt>c.size()</tt> applications of the predicate.</ins>
<p/>
<ins>-5- <i>Remarks:</i> Stable (16.4.6.8 <a href="https://wg21.link/algorithm.stable">[algorithm.stable]</a>). 
If an invocation of <tt>erase_if</tt> exits via an exception, <tt>c</tt> is in a valid but
unspecified state (3.66 <a href="https://wg21.link/defns.valid">[defns.valid]</a>). </ins>
<p/>
<ins>
[<i>Note 1</i>: <tt>c</tt> still meets its invariants, but can be empty. &mdash; <i>end note</i>]
</ins>
</p>
</blockquote>
</blockquote>
</li>
<li><p>Modify 24.6.12.5 <a href="https://wg21.link/flat.multiset.erasure">[flat.multiset.erasure]</a> as indicated:</p>
<blockquote>
<pre>
template&lt;class Key, class Compare, class KeyContainer, class Predicate&gt;
  typename flat_multiset&lt;Key, Compare, KeyContainer&gt;::size_type
    erase_if(flat_multiset&lt;Key, Compare, KeyContainer&gt;&amp; c, Predicate pred);
</pre>
<blockquote>
<p>
<del>-1- <i>Effects:</i> Equivalent to:</del>
</p>
<blockquote>
<pre>
<del>auto [erase_first, erase_last] = ranges::remove_if(c, pred);
auto n = erase_last - erase_first;
c.erase(erase_first, erase_last);
return n;</del>
</pre>
</blockquote>
<p>
<ins>
-1- <i>Preconditions:</i> <tt>Key</tt> meets the <i>Cpp17MoveAssignable</i> requirements.
</ins>
<p/>
<ins>
-2- <i>Effects:</i> Let <i>E</i> be <tt>bool(pred(as_const(e)))</tt>. 
Erases all elements <tt>e</tt> in <tt>c</tt> for which <i>E</i> holds.
</ins>
<p/>
<ins>-3- <i>Returns:</i> The number of elements erased.</ins>
<p/>
<ins>-4- <i>Complexity:</i> Exactly <tt>c.size()</tt> applications of the predicate.</ins>
<p/>
<ins>-5- <i>Remarks:</i> Stable (16.4.6.8 <a href="https://wg21.link/algorithm.stable">[algorithm.stable]</a>). 
If an invocation of <tt>erase_if</tt> exits via an exception, <tt>c</tt> is in a valid but
unspecified state (3.66 <a href="https://wg21.link/defns.valid">[defns.valid]</a>). </ins>
<p/>
<ins>
[<i>Note 1</i>: <tt>c</tt> still meets its invariants, but can be empty. &mdash; <i>end note</i>]
</ins>
</p>
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3880" href="https://cplusplus.github.io/LWG/lwg-active.html#3880">3880</a>. Clarify <tt>operator+=</tt> complexity for <tt>{chunk,stride}_view::<i>iterator</i></tt></h3>
<p><b>Section:</b> 26.7.27.7 <a href="https://wg21.link/range.chunk.fwd.iter">[range.chunk.fwd.iter]</a>, 26.7.30.3 <a href="https://wg21.link/range.stride.iterator">[range.stride.iterator]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Tim Song <b>Opened:</b> 2023-02-09 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
The intent was that the precondition allows the call to <tt>ranges::advance</tt>,
which otherwise would have time linear in the argument of <tt>operator+=</tt>,
to actually be implemented using <tt>operator+=</tt> or equivalent for all but 
the last step. This is at best very non-obvious and should be clarified.
</p>

<p><i>[Issaquah 2023-02-10; LWG issue processing]</i></p>

<p>Move to Immediate for C++23</p>



<p id="res-3880"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4928">N4928</a>.
</p>
<ol>
<li><p>Modify 26.7.27.7 <a href="https://wg21.link/range.chunk.fwd.iter">[range.chunk.fwd.iter]</a> p13 as indicated:</p>
<blockquote>
<pre>
constexpr <i>iterator</i>&amp; operator+=(difference_type x)
  requires random_access_range&lt;<i>Base</i>&gt;;
</pre>
<blockquote>
<p> -12- <i>Preconditions:</i> If <tt>x</tt> is positive, 
<tt>ranges::distance(<i>current_</i>, <i>end_</i>) > <i>n_</i> * (x - 1)</tt> is <tt>true</tt>.
<p/>
[<i>Note 1</i>: If <tt>x</tt> is negative, 
the <i>Effects</i> paragraph implies a precondition. &mdash; <i>end note</i>]
<p/>
-13- <i>Effects:</i> Equivalent to:
</p>
<blockquote>
<pre>
if (x > 0) {
  <ins>ranges::advance(<i>current_</i>, <i>n_</i> * (x - 1));</ins>
  <i>missing_</i> = ranges::advance(<i>current_</i>, <i>n_</i><del> * x</del>, <i>end_</i>);
} else if (x &lt; 0) {
  ranges::advance(<i>current_</i>, <i>n_</i> * x + <i>missing_</i>);
  <i>missing_</i> = 0;
}
return *this;
</pre>
</blockquote>
</blockquote>
</blockquote>
</li>
<li><p>Modify 26.7.30.3 <a href="https://wg21.link/range.stride.iterator">[range.stride.iterator]</a> p14 as indicated:</p>
<blockquote>
<pre>
constexpr <i>iterator</i>&amp; operator+=(difference_type n) requires random_access_range&lt;<i>Base</i>&gt;;
</pre>
<blockquote>
<p> -13- <i>Preconditions:</i> If <tt>n</tt> is positive, 
<tt>ranges::distance(<i>current_</i>, <i>end_</i>) > <i>stride_</i> * (n - 1)</tt> is <tt>true</tt>.
<p/>
[<i>Note 1</i>: If <tt>n</tt> is negative, 
the <i>Effects</i> paragraph implies a precondition. &mdash; <i>end note</i>]
<p/>
-14- <i>Effects:</i> Equivalent to:
</p>
<blockquote>
<pre>
if (n > 0) {
  <ins>ranges::advance(<i>current_</i>, <i>stride_</i> * (n - 1));</ins>
  <i>missing_</i> = ranges::advance(<i>current_</i>, <i>stride_</i><del> * n</del>, <i>end_</i>);
} else if (n &lt; 0) {
  ranges::advance(<i>current_</i>, <i>stride_</i> * n + <i>missing_</i>);
  <i>missing_</i> = 0;
}
return *this;
</pre>
</blockquote>
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3><a name="3881" href="https://cplusplus.github.io/LWG/lwg-active.html#3881">3881</a>. Incorrect formatting of container adapters backed by <tt>std::string</tt></h3>
<p><b>Section:</b> 24.6.13 <a href="https://wg21.link/container.adaptors.format">[container.adaptors.format]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Immediate">Immediate</a>
 <b>Submitter:</b> Victor Zverovich <b>Opened:</b> 2023-02-10 <b>Last modified:</b> 2023-02-10</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
According to 24.6.13 <a href="https://wg21.link/container.adaptors.format">[container.adaptors.format]</a> container adapters such as <tt>std::stack</tt> are 
formatted by forwarding to the underlying container:
</p>
<blockquote><pre>
template&lt;class FormatContext&gt;
  typename FormatContext::iterator
    format(<i>maybe-const-adaptor</i>&amp; r, FormatContext&amp; ctx) const;
</pre>
<blockquote>
<p>
<i>Effects</i>: Equivalent to: <tt>return <i>underlying_</i>.format(r.c, ctx);</tt>
</p>
</blockquote>
</blockquote>
<p>
This gives expected results for <tt>std::stack&lt;T&gt;</tt> and most types of underlying container:
</p>
<blockquote><pre>
auto s = std::format("{}", std::stack(std::deque{'a', 'b', 'c'}));
// s == "['a', 'b', 'c']"
</pre></blockquote>
<p>
However, when the underlying container is <tt>std::string</tt> the output is:
</p>
<blockquote><pre>
auto s = std::format("{}", std::stack{std::string{"abc"}});
// s == "abc"
</pre></blockquote>
<p>
This is clearly incorrect because <tt>std::stack</tt> itself is not a string (it is only backed by a string) 
and inconsistent with formatting of ranges where non-string range types are formatted as comma-separated values 
delimited by <tt>'['</tt> and <tt>']'</tt>. The correct output in this case would be <tt>['a', 'b', 'c']</tt>.
<p/>
Here is an illustration of this issue on godbolt using {fmt} and an implementation of the formatter for container 
adapters based on the one from the standard: <a href="https://godbolt.org/z/P1nrM1986">https://godbolt.org/z/P1nrM1986</a>.
<p/>
A simple fix is to wrap the underlying container in <tt>std::views::all(_t)</tt> 
(<a href="https://godbolt.org/z/8MT1be838">https://godbolt.org/z/8MT1be838</a>).
</p>

<p><strong>Previous resolution [SUPERSEDED]:</strong></p>
<blockquote class="note">


<p>
This wording is relative to <a href="https://wg21.link/N4928">N4928</a>.
</p>

<ol>
<li><p>Modify 24.6.13 <a href="https://wg21.link/container.adaptors.format">[container.adaptors.format]</a> as indicated:</p>

<blockquote>
<p>
-1- For each of <tt>queue</tt>, <tt>priority_queue</tt>, and <tt>stack</tt>, the library provides the following formatter specialization
where <tt><i>adaptor-type</i></tt> is the name of the template:
</p>
<blockquote>
<pre>
namespace std {
  template&lt;class charT, class T, formattable&lt;charT&gt; Container, class... U&gt;
  struct formatter&lt;<i>adaptor-type</i>&lt;T, Container, U...&gt;, charT&gt; {
  private:
    using <i>maybe-const-adaptor</i> =                       // <i>exposition only</i>
      <i>fmt-maybe-const</i>&lt;<i>adaptor-type</i>&lt;T, Container, U...&gt;, charT&gt;;
    formatter&lt;<ins>views::all_t&lt;const</ins> Container<ins>&amp;&gt;</ins>, charT&gt; <i>underlying_</i>;          // <i>exposition only</i>

  public:
    template&lt;class ParseContext&gt;
      constexpr typename ParseContext::iterator
        parse(ParseContext&amp; ctx);

    template&lt;class FormatContext&gt;
      typename FormatContext::iterator
        format(<i>maybe-const-adaptor</i>&amp; r, FormatContext&amp; ctx) const;
  };
}
</pre>
</blockquote>
[&hellip;]
<pre>
template&lt;class FormatContext&gt;
  typename FormatContext::iterator
    format(<i>maybe-const-adaptor</i>&amp; r, FormatContext&amp; ctx) const;
</pre>
<blockquote>
<p>
-3- <i>Effects</i>: Equivalent to: <tt>return <i>underlying_</i>.format(<ins>views::all(</ins>r.c<ins>)</ins>, ctx);</tt>
</p>
</blockquote>
</blockquote>

</li>

</ol>
</blockquote>


<p><i>[2023-02-10 Tim provides updated wording]</i></p>

<p>The container elements may not be const-formattable so we cannot 
use the <tt>const</tt> formatter unconditionally. Also the current wording 
is broken because an adaptor is not range and we cannot use 
<tt><i>fmt-maybe-const</i></tt> on the adaptor &mdash; only the underlying container.</p>

<p><i>[Issaquah 2023-02-10; LWG issue processing]</i></p>

<p>Move to Immediate for C++23</p>



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

<ol>
<li><p>Modify 24.6.13 <a href="https://wg21.link/container.adaptors.format">[container.adaptors.format]</a> as indicated:</p>

<blockquote>
<p>
-1- For each of <tt>queue</tt>, <tt>priority_queue</tt>, and <tt>stack</tt>, the library provides the following formatter specialization
where <tt><i>adaptor-type</i></tt> is the name of the template:
</p>
<blockquote>
<pre>
namespace std {
  template&lt;class charT, class T, formattable&lt;charT&gt; Container, class... U&gt;
  struct formatter&lt;<i>adaptor-type</i>&lt;T, Container, U...&gt;, charT&gt; {
  private:
    <ins>using <i>maybe-const-container</i> =                     // <i>exposition only</i>
      <i>fmt-maybe-const</i>&lt;Container, charT&gt;;</ins>
    using <i>maybe-const-adaptor</i> =                       // <i>exposition only</i>
      <i><del>fmt-</del>maybe-const</i>&lt;<ins>is_const_v&lt;<i>maybe-const-container</i>&gt;, </ins><i>adaptor-type</i>&lt;T, Container, U...&gt;<del>, charT</del>&gt;; <ins>// <i>see 26.2 <a href="https://wg21.link/ranges.syn">[ranges.syn]</a></i></ins>
      
    formatter&lt;<ins>ranges::ref_view&lt;<i>maybe-const-container</i>&gt;</ins><del>Container</del>, charT&gt; <i>underlying_</i>;          // <i>exposition only</i>

  public:
    template&lt;class ParseContext&gt;
      constexpr typename ParseContext::iterator
        parse(ParseContext&amp; ctx);

    template&lt;class FormatContext&gt;
      typename FormatContext::iterator
        format(<i>maybe-const-adaptor</i>&amp; r, FormatContext&amp; ctx) const;
  };
}
</pre>
</blockquote>
[&hellip;]
<pre>
template&lt;class FormatContext&gt;
  typename FormatContext::iterator
    format(<i>maybe-const-adaptor</i>&amp; r, FormatContext&amp; ctx) const;
</pre>
<blockquote>
<p>
-3- <i>Effects</i>: Equivalent to: <tt>return <i>underlying_</i>.format(r.c, ctx);</tt>
</p>
</blockquote>
</blockquote>

</li>

</ol>





</body>
</html>
