<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8">
<title>C++ Standard Library Issues to be moved in St. Louis</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 Issues to be moved in St. Louis</h1>
<table>
<tr>
<td align="left">Doc. no.</td>
<td align="left">P3341R0</td>
</tr>
<tr>
<td align="left">Date:</td>
<td align="left"><p>2024-06-24</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>
<ul>
<li><a href="#ready">Ready Issues</a></li>
<li><a href="#tentatively_ready">Tentatively Ready Issues</a></li>
</ul>
<h2 id="ready">Ready Issues</h2>
<hr>
<h3 id="3944"><a href="https://cplusplus.github.io/LWG/lwg-active.html#3944">3944</a>. Formatters converting sequences of <code>char</code> to sequences of <code>wchar_t</code></h3>
<p><b>Section:</b> 22.14.6.4 <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#Ready">Ready</a>
 <b>Submitter:</b> Mark de Wever <b>Opened:</b> 2023-06-01 <b>Last modified:</b> 2024-03-18</p>
<p><b>Priority: </b>3
</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>
I noticed some interesting features introduced by the range based
formatters in C++23
</p>
<blockquote><pre>
// Ill-formed in C++20 and C++23
const char* cstr = "hello";
char* str = const_cast&lt;char*&gt;(cstr);
std::format(L"{}", str);
std::format(L"{}",cstr);

// Ill-formed in C++20
// In C++23 they give L"['h', 'e', 'l', 'l', 'o']"
std::format(L"{}", "hello"); // A libc++ bug prevents this from working.
std::format(L"{}", std::string_view("hello"));
std::format(L"{}", std::string("hello"));
std::format(L"{}", std::vector{'h', 'e', 'l', 'l', 'o'});
</pre></blockquote>
<p>
An example is shown <a href="https://godbolt.org/z/P9E6TK3YW">here</a>. This only
shows libc++ since libstdc++ and MSVC STL have not implemented the
formatting ranges papers (<a href="https://wg21.link/P2286R8" title=" Formatting Ranges">P2286R8</a> and <a href="https://wg21.link/P2585R0" title=" Improving default container formatting">P2585R0</a>) yet.
<p/>
The difference between C++20 and C++23 is the existence of range
formatters. These formatters use the formatter specialization
<code>formatter&lt;char, wchar_t&gt;</code> which converts the sequence of <code>char</code>s 
to a sequence of <code>wchar_t</code>s.
<p/>
In this conversion <code>same_as&lt;char, charT&gt;</code> is <code>false</code>, thus the requirements
of the range-type <code>s</code> and <code>?s</code> ([tab:formatter.range.type]) aren't met. So
the following is ill-formed:
</p>
<blockquote><pre>
std::format(L"{:s}", std::string("hello")); // Not L"hello"
</pre></blockquote>
<p>
It is surprising that some string types can be formatted as a sequence
of wide-characters, but others not. A sequence of characters can be a
sequence UTF-8 code units. This is explicitly supported in the width
estimation of string types. The conversion of <code>char</code> to <code>wchar_t</code> will
convert the individual code units, which will give incorrect results for
multi-byte code points. It will not transcode UTF-8 to UTF-16/32. The
current behavior is not in line with the note in
22.14.6.4 <a href="https://wg21.link/format.formatter.spec">[format.formatter.spec]</a>/2
</p>
<blockquote><p>
[<i>Note 1</i>: Specializations such as <code>formatter&lt;wchar_t, char&gt;</code> and
<code>formatter&lt;const char*, wchar_t&gt;</code> that would require implicit
multibyte / wide string or character conversion are disabled. &mdash; <i>end note</i>]
</p></blockquote>
<p>
Disabling this could be done by explicitly disabling the <code>char</code> to <code>wchar_t</code>
sequence formatter. Something along the lines of
</p>
<blockquote><pre>
template&lt;ranges::input_range R&gt;
  requires(format_kind&lt;R&gt; == range_format::sequence &amp;&amp;
           same_as&lt;remove_cvref_t&lt;ranges::range_reference_t&lt;R&gt;&gt;, char&gt;)
struct formatter&lt;R, wchar_t&gt; : __disabled_formatter {};
</pre></blockquote>
<p>
where <code>__disabled_formatter</code> satisfies 22.14.6.4 <a href="https://wg21.link/format.formatter.spec">[format.formatter.spec]</a>/5, would
do the trick. This disables the conversion for all sequences not only
the string types. So <code>vector</code>, <code>array</code>, <code>span</code>, etc. would be disabled.
<p/>
This does not disable the conversion in the <code>range_formatter</code>. This allows
users to explicitly opt in to this formatter for their own
specializations.
<p/>
An alternative would be to only disable this conversion for string type
specializations (22.14.6.4 <a href="https://wg21.link/format.formatter.spec">[format.formatter.spec]</a>/2.2) where <code>char</code> to 
<code>wchar_t</code> is used:
</p>
<blockquote><pre>
template&lt;size_t N&gt; struct formatter&lt;charT[N], charT&gt;;
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>
<p>
Disabling following the following two is not strictly required:
</p>
<blockquote><pre>
template&lt;&gt; struct formatter&lt;char*, wchar_t&gt;;
template&lt;&gt; struct formatter&lt;const char*, wchar_t&gt;;
</pre></blockquote>
<p>
However, if (<code>const</code>) <code>char*</code> becomes an <code>input_range</code> 
in a future version C++, these formatters would become enabled. 
Disabling all five instead of the three required specializations seems like a 
future proof solution.
<p/>
Since there is no enabled narrowing formatter specialization
</p>
<blockquote><pre>
template&lt;&gt; struct formatter&lt;wchar_t, char&gt;;
</pre></blockquote>
<p>
there are no issues for <code>wchar_t</code> to <code>char</code> conversions.
<p/>
Before proceeding with a proposed resolution the following design
questions need to be addressed:
</p>
<ul>
<li><p>Do we want to allow string types of <code>char</code>s to be formatted as
sequences of <code>wchar_t</code>s?</p></li>
<li><p>Do we want to allow non string type sequences of <code>char</code>s to be
formatted as sequences of <code>wchar_t</code>s?</p></li>
<li><p>Should we disable <code>char</code> to <code>wchar_t</code> conversion in the <code>range_formatter</code>?</p></li>
</ul>
<p>
SG16 has indicated they would like to discuss this issue during a telecon.
</p>

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

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

<p><i>[2023-07-26; Mark de Wever provides wording confirmed by SG16]</i></p>

<p><i>[2024-03-18; Tokyo: move to Ready]</i></p>




<p id="res-3944"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4950" title=" Working Draft, Standard for Programming Language C++">N4950</a>.
</p>

<ol>

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

<blockquote class="note">
<p>
[<i>Drafting note</i>: The unwanted conversion happens due to the <code>formatter</code> base class
specialization (22.14.7.3 <a href="https://wg21.link/format.range.fmtdef">[format.range.fmtdef]</a>)
</p>
<pre>
struct <i>range-default-formatter</i>&lt;range_format::sequence, R, charT&gt;
</pre>
<p>
which is defined the header <code>&lt;format&gt;</code>. Therefore the disabling is only
needed in this header) &mdash; <i>end drafting note</i>]
</p>
</blockquote>

<blockquote>
<p>
-2- [&hellip;]
<p/>
The <code>parse</code> member functions of these formatters interpret the format specification as a 
<i>std-format-spec</i> as described in 22.14.2.2 <a href="https://wg21.link/format.string.std">[format.string.std]</a>.
<p/>
[<i>Note 1</i>: Specializations such as <code>formatter&lt;wchar_t, char&gt;</code> <del>and 
<code>formatter&lt;const char*, wchar_t&gt;</code></del> that would require implicit multibyte / wide string 
or character conversion are disabled. &mdash; <i>end note</i>]
<p/>
<ins>
-?- The header <code>&lt;format&gt;</code> provides the following disabled specializations:
</ins>
</p>
<ol style="list-style-type: none">
<li><p><ins>(?.1) &mdash; The string type specializations</ins></p>
<blockquote><pre>
<ins>template&lt;&gt; struct formatter&lt;char*, wchar_t&gt;;
template&lt;&gt; struct formatter&lt;const char*, wchar_t&gt;;
template&lt;size_t N&gt; struct formatter&lt;char[N], wchar_t&gt;;
template&lt;class traits, class Allocator&gt;
  struct formatter&lt;basic_string&lt;char, traits, Allocator&gt;, wchar_t&gt;;
template&lt;class traits&gt;
  struct formatter&lt;basic_string_view&lt;char, traits&gt;, wchar_t&gt;;</ins>
</pre></blockquote>
</li>
</ol>
<p>
-3- For any types <code>T</code> and <code>charT</code> for which neither the library nor the user provides 
an explicit or partial specialization of the class template <code>formatter</code>, 
<code>formatter&lt;T, charT&gt;</code> is disabled.
</p>
</blockquote>
</li>

</ol>




<h2 id="tentatively_ready">Tentatively Ready Issues</h2>
<hr>
<h3 id="4060"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4060">4060</a>. <code>submdspan</code> preconditions do not forbid creating invalid pointer</h3>
<p><b>Section:</b> 24.7.3.7.7 <a href="https://wg21.link/mdspan.sub.sub">[mdspan.sub.sub]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Mark Hoemmen <b>Opened:</b> 2024-03-26 <b>Last modified:</b> 2024-05-08</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
Oliver Lee and Ryan Wooster pointed out to us that creating a <code>submdspan</code> with zero-length 
<code><i>tuple-like</i></code> or <code>strided_slice</code> slice specifiers at the upper extent can cause 
the Standard <code>submdspan_mapping</code> overloads to access the input <code>mdspan</code>'s mapping 
out of bounds.
This happens in the following line of specification (24.7.3.7.6 <a href="https://wg21.link/mdspan.sub.map">[mdspan.sub.map]</a> p8 in
<a href="https://wg21.link/N4971" title=" Working Draft, Programming Languages — C++">N4971</a> moved to [mdspan.sub.map.common] p8 <b>after</b> the merge of
<a href="https://wg21.link/P2642R6">P2642R6</a>).
</p>
<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;">
<p>
Let <code>offset</code> be a value of type <code>size_t</code> equal to <code>(*this)(<i>first_</i>&lt;index_type, P&gt;(slices...)...)</code>.
</p>
</blockquote>
<p>
If <code>data_handle_type</code> is a pointer to an array, then the resulting offset can be larger than 
<code>required_span_size()</code>, thus making the pointer invalid (not just one past the end). In a 
constexpr context, the result is ill-formed. With the <a href="https://github.com/kokkos/mdspan">reference 
<code>mdspan</code> implementation</a>, Clang can actually report a build error (e.g., for out-of-bounds access 
to a <code>std::array</code>). The contributed example illustrates this.
<p/>
Oliver and Ryan offer the following example and analysis:
</p>
<blockquote style="border-left: 3px solid #ccc;padding-left: 15px;">
<p>
Example 1:
</p>
<blockquote><pre>
auto x = std::array&lt;int, 3&gt;{};
auto A = mdspan{x.data(), extents{3}}; 
auto B = submdspan(A, pair{3, 3});
</pre></blockquote>
<p>
B is an <code>mdspan</code> with zero elements.
<p/>
Example 2:
</p>
<blockquote><pre>
auto y = std::array&lt;int, 9&gt;{};
auto C = mdspan{y.data(), extents{3, 3}}; 
auto D = submdspan(C, pair{3, 3}, pair{3, 3});
</pre></blockquote>
<p>
A precondition for each slice specifier is (24.7.3.7.5 <a href="https://wg21.link/mdspan.sub.extents">[mdspan.sub.extents]</a>):
</p>
<blockquote><pre>
0 &le; <i>first_</i>&lt;index_type, <i>k</i>&gt;(slices...) &le; <i>last_</i>&lt;<i>k</i>&gt;(src.extents(), slices...) &le; src.extent(<i>k</i>).
</pre></blockquote>
<p>
Our understanding is that precondition is satisfied. In the second example, <code><i>first_</i>&lt;0&gt;</code> 
is 3 and <code><i>first_</i>&lt;1&gt;</code> is also 3.
<p/>
However, the submapping offset is defined as <code>(*this)(<i>first_</i>&lt;index_type, P&gt;(slices...)...)</code>, 
which then can result in an invalid data handle of the <code>submdspan</code>, even if the data handle is never 
accessed/dereferenced.
<p/>
<a href="https://godbolt.org/z/zaMTbMEK7">godbolt demo</a>
</p>
</blockquote>
<p>
We expect this situation to come up in practice.
<p/>
Suppose we have an <code>N x N</code> mdspan representing a matrix <code>A</code>, and we want to partition it 
into a <code>2 x 2</code> "matrix of matrices" (also called a "block matrix"). This partitioning is a 
common operation in linear algebra algorithms such as matrix factorizations.  
Examples of this <code>2 x 2</code> partitioning appear in <a href="https://wg21.link/P2642" title=" Padded mdspan layouts">P2642</a> and <a href="https://wg21.link/P1673" title=" A free function linear algebra interface based on the BLAS">P1673</a>.
</p>
<blockquote><pre>
mdspan A{A_ptr, N, N};

size_t p = partition_point(N); // <i>integer in 0, 1, &hellip;, N (inclusive)</i>
auto A_00 = submdspan(A, tuple{0, p}, tuple{0, p});
auto A_10 = submdspan(A, tuple{p, N}, tuple{0, 0});
auto A_01 = submdspan(A, tuple{0, p}, tuple{p, N});
auto A_11 = submdspan(A, tuple{p, N}, tuple{p, N});
</pre></blockquote>
<p>
Table illustrating the resulting <code>2 x 2</code> block matrix follows:
</p>
<table border="1">
<tr>
  <td><code>A_00</code></td>
  <td><code>A_01</code></td>
</tr>
<tr>
  <td><code>A_10</code></td>
  <td><code>A_11</code></td>
</tr>
</table> 
<p>
It's valid for <code>p</code> to be <code>0</code>. That makes every block but <code>A_11</code> have zero size.
Thus, it should also be valid for <code>p</code> to be <code>N</code>. That makes every block but 
<code>A_00</code> have zero size. However, that leads to the aforementioned UB.
<p/>
It doesn't make sense to change <code><i>first_</i></code> or <code><i>last_</i></code>. The definitions of 
<code><i>first_</i></code> and <code><i>last_</i></code> are meant to turn the slice specifier into a pair of bounds.
Since <code>submdspan(A, tuple{p, N}, tuple{p, N})</code> is valid even if <code>p</code> equals <code>N</code>,
then that strongly suggests that <code><i>first_</i>&lt;0&gt;</code> and <code><i>first_</i>&lt;1&gt;</code> 
should always be <code>p</code>, even if <code>p</code> equals <code>N</code>.
<p/>
As a result, we find ourselves needing to change <code>submdspan_mapping</code>. This will affect both 
the Standard <code>submdspan_mapping</code> overloads, and any custom (user-defined) overloads.
</p>

<p><i>[2024-05-08; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after five votes in favour during reflector poll.
</p>



<p id="res-4060"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4971" title=" Working Draft, Programming Languages — C++">N4971</a> <b>after</b> the merge of <a href="https://wg21.link/P2642R6">P2642R6</a>.
</p>

<ol>
<li><p>Modify the new 24.7.3.7.6.1 <a href="https://wg21.link/mdspan.sub.map.common">[mdspan.sub.map.common]</a> as indicated:</p>

<blockquote>
<p>
-8- <ins>If <code><i>first_</i>&lt;index_type, <i>k</i>&gt;(slices...)</code> equals <code>extents().extent(<i>k</i>)</code> 
for any rank index <code><i>k</i></code> of <code>extents()</code>, then l</ins><del>L</del>et <code>offset</code> be 
a value of type <code>size_t</code> equal to <ins><code>(*this).required_span_size()</code>. Otherwise, let 
<code>offset</code> be a value of type <code>size_t</code> equal to</ins> 
<code>(*this)(<i>first_</i>&lt;index_type, P&gt;(slices...)...)</code>.
</p>
</blockquote>
</li>

<li><p>Modify 24.7.3.7.7 <a href="https://wg21.link/mdspan.sub.sub">[mdspan.sub.sub]</a> as indicated:</p>

<blockquote class="note">
<p>
As a drive-by readability fix, we also propose changing a variable name in paragraph 6
as indicated below.
</p>
</blockquote>

<blockquote>
<pre>
template&lt;class ElementType, class Extents, class LayoutPolicy,
         class AccessorPolicy, class... SliceSpecifiers&gt;
  constexpr auto submdspan(
    const mdspan&lt;ElementType, Extents, LayoutPolicy, AccessorPolicy&gt;&amp; src,
    SliceSpecifiers... slices) -&gt; <i>see below</i>;
</pre>
<blockquote>
<p>
-1- Let <code>index_type</code> be <code>typename Extents::index_type</code>.
<p/>
-2- Let <code>sub_map_offset</code> be the result of <code>submdspan_mapping(src.mapping(), slices...)</code>.
<p/>
[&hellip;]
<p/>
-3- <i>Constraints</i>: [&hellip;]
<p/>
-4- <i>Mandates</i>: [&hellip;]
<p/>
-5-<i>Preconditions</i>: [&hellip;]
<p/>
-6- <i>Effects</i>: Equivalent to:
</p>
<blockquote><pre>
auto sub_map_<ins>result</ins><del>offset</del> = submdspan_mapping(src.mapping(), slices...);
return mdspan(src.accessor().offset(src.data(), sub_map_<ins>result</ins><del>offset</del>.offset),
              sub_map_<ins>result</ins><del>offset</del>.mapping,
              AccessorPolicy::offset_policy(src.accessor()));
</pre></blockquote>
</blockquote>
</blockquote>
</li>
</ol>





<hr>
<h3 id="4061"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4061">4061</a>. Should <code>std::basic_format_context</code> be default-constructible/copyable/movable?</h3>
<p><b>Section:</b> 22.14.6.7 <a href="https://wg21.link/format.context">[format.context]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Jiang An <b>Opened:</b> 2024-03-24 <b>Last modified:</b> 2024-03-26</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#format.context">issues</a> in [format.context].</p>
<p><b>Discussion:</b></p>
<p>
Per 22.14.6.7 <a href="https://wg21.link/format.context">[format.context]</a>, it seems that <code>std::basic_format_context</code> has a default 
constructor that is effectively defaulted, which means that it is default constructible if and only 
if <code>OutIt</code> is default constructible. Currently only libstdc++ makes it conditionally default 
constructible, while libc++ and MSVC STL (together with fmtlib) make it never default constructible.
<p/>
It seems that <code>basic_format_context</code> objects are supposed to be created by the implementation 
in some internal way, and user codes are only supposed to modify existing <code>basic_format_context</code> 
objects during formatting.
</p>

<p><i>[2024-05-08; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after six votes in favour during reflector poll.
</p>



<p id="res-4061"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4971" title=" Working Draft, Programming Languages — C++">N4971</a>.
</p>

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

<blockquote>
<pre>
namespace std {
  template&lt;class Out, class charT&gt;
  class basic_format_context {
    basic_format_args&lt;basic_format_context&gt; args_; // <i>exposition only</i>
    Out out_;                                      // <i>exposition only</i>

    <ins>basic_format_context(const basic_format_context&amp;) = delete;
    basic_format_context&amp; operator=(const basic_format_context&amp;) = delete;</ins>
  public:
    using iterator = Out;
    using char_type = charT;
    template&lt;class T&gt; using formatter_type = formatter&lt;T, charT&gt;;
    
    basic_format_arg&lt;basic_format_context&gt; arg(size_t id) const noexcept;
    std::locale locale();
    
    iterator out();
    void advance_to(iterator it);
  };
}
</pre>
</blockquote>
</li>
</ol>





<hr>
<h3 id="4071"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4071">4071</a>. <code>reference_wrapper</code> comparisons are not SFINAE-friendly</h3>
<p><b>Section:</b> 22.10.6.6 <a href="https://wg21.link/refwrap.comparisons">[refwrap.comparisons]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Jonathan Wakely <b>Opened:</b> 2024-04-19 <b>Last modified:</b> 2024-04-24</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
<a href="https://wg21.link/P2944R3" title=" Comparisons for reference_wrapper">P2944R3</a> added these hidden friends to <code class='backtick'>reference_wrapper</code>:
</p>
<pre><code>
   friend constexpr <em>synth-three-way-result</em>&lt;T&gt; operator&lt;=&gt;(reference_wrapper, reference_wrapper);
   friend constexpr <em>synth-three-way-result</em>&lt;T&gt; operator&lt;=&gt;(reference_wrapper, const T&amp;);
   friend constexpr <em>synth-three-way-result</em>&lt;T&gt; operator&lt;=&gt;(reference_wrapper, reference_wrapper&lt;const T&gt;);
</code></pre>

<p>
These functions are not templates, and so their declarations are ill-formed
for any type that does have any comparison operators, e.g.
<pre><code>
    struct A { } a;
    std::reference_wrapper&lt;A&gt; r(a);
</code></pre>
</p>
<p>
Instantiating <code>reference_wrapper&lt;A&gt;</code> will instantiate
the declarations of the hidden friends, which will attempt to determine the
return types of the <code>operator&lt;=&gt;</code> functions.
That fails because <em><code class='backtick'>synth-three-way</code></em> is constrained
and can't be called with arguments of type <code class='backtick'>A</code>.
</p>

<p>
This can be solved by changing those functions into templates, so they
aren't instantiated eagerly, e.g.,
<pre><code>
    <ins>template&lt;class U = T&gt;</ins>
    friend constexpr <em>synth-three-way-result</em>&lt;<del>T</del><ins>U</ins>&gt; operator&lt;=&gt;(reference_wrapper, reference_wrapper);
</code></pre>
or by giving them a deduced return type (so that it isn't instantiated eagerly)
and constraining them to only be callable when valid:
<pre><code>
    friend constexpr <del><em>synth-three-way-result</em>&lt;T&gt;</del><ins>auto</ins> operator&lt;=&gt;(reference_wrapper x, reference_wrapper y)
    <ins>requires requires (const T t) { <em>synth-three-way</em>(t, t); }</ins>
</code></pre>
The second alternative is used in the proposed resolution.
</p>
<p>
In practice the <em>requires-clause</em> can be implemented more simply
(and efficiently) by checking the constraints of <em>synth-three-way</em>
directly:
<pre><code>    requires (const T t) { { t &lt; t } -> <em>boolean-testable</em>; }
</code></pre>
but when specified in prose in a <em>Constraints</em>: element it seems
clearer to just use <code><em>synth-three-way</em>(x.get(), y.get())</code>.
</p>

<p>The proposed resolution has been committed to libstdc++'s master branch.</p>

<p><i>[2024-05-08; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after eight votes in favour during reflector poll.
</p>



<p id="res-4071"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</a>.
</p>
<ol>
<li><p>Modify 22.10.6.1 <a href="https://wg21.link/refwrap.general">[refwrap.general]</a> as indicated:</p>

<blockquote>
<pre><code>
   // [refwrap.comparisons], comparisons
   friend constexpr bool operator==(reference_wrapper, reference_wrapper);
   friend constexpr bool operator==(reference_wrapper, const T&amp;);
   friend constexpr bool operator==(reference_wrapper, reference_wrapper&lt;const T&gt;);

   friend constexpr <del><em>synth-three-way-result</em>&lt;T&gt;</del><ins>auto</ins> operator&lt;=&gt;(reference_wrapper, reference_wrapper);
   friend constexpr <del><em>synth-three-way-result</em>&lt;T&gt;</del><ins>auto</ins> operator&lt;=&gt;(reference_wrapper, const T&amp;);
   friend constexpr <del><em>synth-three-way-result</em>&lt;T&gt;</del><ins>auto</ins> operator&lt;=&gt;(reference_wrapper, reference_wrapper&lt;const T&gt;);
</code></pre>
</blockquote>

</li>
<li><p>Modify 22.10.6.6 <a href="https://wg21.link/refwrap.comparisons">[refwrap.comparisons]</a> as indicated:</p>
<blockquote>
<pre><code>
friend constexpr <del><em>synth-three-way-result</em>&lt;T&gt;</del><ins>auto</ins> operator&lt;=&gt;(reference_wrapper x, reference_wrapper y);
</code></pre>

<p>
<ins>-?-
<em>Constraints</em>:
The expression
<code><em>synth-three-way</em>(x.get(), y.get())</code>
is well-formed.
</ins>
</p>

<p>-7-
<em>Returns</em>: <code><em>synth-three-way</em>(x.get(), y.get())</code>.
</p>

<pre><code>
friend constexpr <del><em>synth-three-way-result</em>&lt;T&gt;</del><ins>auto</ins> operator&lt;=&gt;(reference_wrapper x, const T&amp; y);
</code></pre>

<p>
<ins>-?-
<em>Constraints</em>:
The expression
<code><em>synth-three-way</em>(x.get(), y)</code>
is well-formed.
</ins>
</p>

<p>-8-
<em>Returns</em>: <code><em>synth-three-way</em>(x.get(), y)</code>.
</p>

<pre><code>
friend constexpr <del><em>synth-three-way-result</em>&lt;T&gt;</del><ins>auto</ins> operator&lt;=&gt;(reference_wrapper x, reference_wrapper&lt;const T&gt; y);
</code></pre>

<p>-9-
<em>Constraints</em>: <code>is_const_v&lt;T&gt;</code> is <code class='backtick'>false</code>.
<ins>
The expression
<code><em>synth-three-way</em>(x.get(), y.get())</code>
is well-formed.
</ins>
</p>

<p>-10-
<em>Returns</em>: <code><em>synth-three-way</em>(x.get(), y.get())</code>.
</p>
</blockquote>
</li>
</ol>






<hr>
<h3 id="4074"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4074">4074</a>. <code><i>compatible-joinable-ranges</i></code> is underconstrained</h3>
<p><b>Section:</b> 26.7.15.2 <a href="https://wg21.link/range.join.with.view">[range.join.with.view]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2024-04-21 <b>Last modified:</b> 2024-04-27</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#range.join.with.view">active issues</a> in [range.join.with.view].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#range.join.with.view">issues</a> in [range.join.with.view].</p>
<p><b>Discussion:</b></p>
<p>
<code>join_with_view</code> requires the value type, reference and rvalue reference of the inner range 
and pattern range to share common (reference) types through <code><i>compatible-joinable-ranges</i></code>.
<p/>
However, unlike what <code>concat_view</code> and <code>generator</code> do, this concept only requires that 
these three types be valid and does not further check the relationship between them to be compatible 
with the <code>indirectly_readable</code> requirement for <code>input_iterator</code>.
This results in a validly-constructed <code>join_with_view</code> that may not model <code>input_range</code>, 
which seems unintended.
<p/>
The proposed resolution aliases <code><i>compatible-joinable-ranges</i></code> to <code><i>concatable</i></code> 
i.e. specialization for two ranges to fully constrain, and I believe this could also be a better fit for 
LWG <a href="https://cplusplus.github.io/LWG/lwg-active.html#3971" title="Join ranges of rvalue references with ranges of prvalues (Status: Open)">3971</a>.
</p>

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

<p>
This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</a>.
</p>

<ol>
<li><p>Modify 26.7.15.2 <a href="https://wg21.link/range.join.with.view">[range.join.with.view]</a> as indicated:</p>
  
<blockquote>
<pre>
namespace std::ranges {
  template&lt;class R, class P&gt;
    concept <i>compatible-joinable-ranges</i> = <ins><i>concatable</i>&lt;R, P&gt;;</ins>  // <i>exposition only</i>
        <del>common_with&lt;range_value_t&lt;R&gt;, range_value_t&lt;P&gt;&gt; &amp;&amp;
        common_reference_with&lt;range_reference_t&lt;R&gt;, range_reference_t&lt;P&gt;&gt; &amp;&amp;
        common_reference_with&lt;range_rvalue_reference_t&lt;R&gt;, range_rvalue_reference_t&lt;P&gt;&gt;;</del>
  
  [&hellip;]
}
</pre>
</blockquote>
</li>

</ol>
</blockquote>

<p><i>[2024-04-24; Hewill Kang provides improved wording]</i></p>


<p><i>[2024-05-08; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after five votes in favour during reflector poll.
</p>



<p id="res-4074"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</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 {
  [&hellip;]
  // <i>26.7.15 <a href="https://wg21.link/range.join.with">[range.join.with]</a></i>, <i>join with view</i>
  <del>template&lt;class R, class P&gt;
    concept <i>compatible-joinable-ranges</i> = <i>see below</i>; // <i>exposition only</i></del>

  template&lt;input_range V, forward_range Pattern&gt;
    requires <del>view&lt;V&gt; &amp;&amp; input_range&lt;range_reference_t&lt;V&gt;&gt;
          &amp;&amp; view&lt;Pattern&gt;
          &amp;&amp; <i>compatible-joinable-ranges</i>&lt;range_reference_t&lt;V&gt;, Pattern&gt;</del>
          <ins><i>see below</i></ins>
  class join_with_view;                                                             // <i>freestanding</i>
  [&hellip;]
}
</pre>
</blockquote>
</li>

<li><p>Modify 26.7.15.2 <a href="https://wg21.link/range.join.with.view">[range.join.with.view]</a> as indicated:</p>
  
<blockquote>
<pre>
namespace std::ranges {
  <del>template&lt;class R, class P&gt;
    concept <i>compatible-joinable-ranges</i> =            // <i>exposition only</i>
        common_with&lt;range_value_t&lt;R&gt;, range_value_t&lt;P&gt;&gt; &amp;&amp;
        common_reference_with&lt;range_reference_t&lt;R&gt;, range_reference_t&lt;P&gt;&gt; &amp;&amp;
        common_reference_with&lt;range_rvalue_reference_t&lt;R&gt;, range_rvalue_reference_t&lt;P&gt;&gt;;</del>
  
  [&hellip;]

  template&lt;input_range V, forward_range Pattern&gt;
    requires view&lt;V&gt; &amp;&amp; input_range&lt;range_reference_t&lt;V&gt;&gt;
          &amp;&amp; view&lt;Pattern&gt;
          &amp;&amp; <i><del>compatible-joinable-ranges</del><ins>concatable</ins></i>&lt;range_reference_t&lt;V&gt;, Pattern&gt;
  class join_with_view : public view_interface&lt;join_with_view&lt;V, Pattern&gt;&gt; {
    [&hellip;]
    constexpr auto begin() const
      requires forward_range&lt;const V&gt; &amp;&amp;
               forward_range&lt;const Pattern&gt; &amp;&amp;
               is_reference_v&lt;range_reference_t&lt;const V&gt;&gt; &amp;&amp;
               input_range&lt;range_reference_t&lt;const V&gt;&gt; <ins>&amp;&amp;
               <i>concatable</i>&lt;range_reference_t&lt;const V&gt;, const Pattern&gt;</ins> {
      return <i>iterator</i>&lt;true&gt;{*this, ranges::begin(<i>base_</i>)};
    }
    [&hellip;]
    constexpr auto end() const
      requires forward_range&lt;const V&gt; &amp;&amp; forward_range&lt;const Pattern&gt; &amp;&amp;
               is_reference_v&lt;range_reference_t&lt;const V&gt;&gt; &amp;&amp;
               input_range&lt;range_reference_t&lt;const V&gt;&gt; <ins>&amp;&amp;
               <i>concatable</i>&lt;range_reference_t&lt;const V&gt;, const Pattern&gt;</ins> {
      [&hellip;]
    }
  };
}
</pre>
</blockquote>
</li>

<li><p>Modify 26.7.15.3 <a href="https://wg21.link/range.join.with.iterator">[range.join.with.iterator]</a> as indicated:</p>
  
<blockquote>
<pre>
namespace std::ranges {
  template&lt;input_range V, forward_range Pattern&gt;
    requires view&lt;V&gt; &amp;&amp; input_range&lt;range_reference_t&lt;V&gt;&gt;
          &amp;&amp; view&lt;Pattern&gt; &amp;&amp; <i><del>compatible-joinable-ranges</del><ins>concatable</ins></i>&lt;range_reference_t&lt;V&gt;, Pattern&gt;
  template&lt;bool Const&gt;
  class join_with_view&lt;V, Pattern&gt;::<i>iterator</i> {
    [&hellip;]
  };
}
</pre>
</blockquote>
</li>

<li><p>Modify 26.7.15.4 <a href="https://wg21.link/range.join.with.sentinel">[range.join.with.sentinel]</a> as indicated:</p>
  
<blockquote>
<pre>
namespace std::ranges {
  template&lt;input_range V, forward_range Pattern&gt;
    requires view&lt;V&gt; &amp;&amp; input_range&lt;range_reference_t&lt;V&gt;&gt;
          &amp;&amp; view&lt;Pattern&gt; &amp;&amp; <i><del>compatible-joinable-ranges</del><ins>concatable</ins></i>&lt;range_reference_t&lt;V&gt;, Pattern&gt;
  template&lt;bool Const&gt;
  class join_with_view&lt;V, Pattern&gt;::<i>sentinel</i> {
    [&hellip;]
  };
}
</pre>
</blockquote>
</li>

</ol>





<hr>
<h3 id="4076"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4076">4076</a>. <code>concat_view</code> should be freestanding</h3>
<p><b>Section:</b> 17.3.2 <a href="https://wg21.link/version.syn">[version.syn]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2024-04-21 <b>Last modified:</b> 2024-04-21</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#version.syn">active issues</a> in [version.syn].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#version.syn">issues</a> in [version.syn].</p>
<p><b>Discussion:</b></p>
<p>
<code>concat_view</code> can be freestanding, but this never seems to come up in the discussion, 
which seems to be an oversight.
</p>

<p><i>[2024-04-21; Daniel comments]</i></p>

<p>
The specification of some member functions of <code>concat_view</code> seem to depend on freestanding-deleted
<code>get</code> overloads for <code>variant</code>, but so does <code>join_with_view</code>, which is marked as freestanding,
so it does not seem to be a good reason to accept <code>join_with_view</code> but not <code>concat_view</code> as freestanding.
</p>

<p><i>[2024-05-08; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after seven votes in favour during reflector poll.
</p>



<p id="res-4076"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</a>.
</p>

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

<blockquote>
<pre>
#define __cpp_lib_ranges_concat 202403L // <ins><i>freestanding</i>,</ins> <i>also in</i> &lt;ranges&gt;
</pre>
</blockquote>
</li>

<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 {
  [&hellip;]
  // <i>26.7.18 <a href="https://wg21.link/range.concat">[range.concat]</a>, concat view</i>
  template&lt;input_range... Views&gt;
    requires <i>see below</i>
  class concat_view;                                                                <ins>// <i>freestanding</i></ins>
  
  namespace views { inline constexpr <i>unspecified</i> concat = <i>unspecified</i>; }            <ins>// <i>freestanding</i></ins>
  [&hellip;]
}
</pre>
</blockquote>
</li>

</ol>





<hr>
<h3 id="4079"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4079">4079</a>. Missing <i>Preconditions</i> in <code>concat_view::<i>iterator</i></code>'s conversion constructor</h3>
<p><b>Section:</b> 26.7.18.3 <a href="https://wg21.link/range.concat.iterator">[range.concat.iterator]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2024-04-26 <b>Last modified:</b> 2024-04-27</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#range.concat.iterator">active issues</a> in [range.concat.iterator].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#range.concat.iterator">issues</a> in [range.concat.iterator].</p>
<p><b>Discussion:</b></p>
<p>
This conversion constructor obtains the alternative iterator of the argument
through <code>std::get</code>, which will throw when the <code>variant</code> is valueless.
We seem to be missing a <i>Preconditions</i> element here.
</p>

<p><i>[2024-05-08; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after seven votes in favour during reflector poll.
</p>



<p id="res-4079"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</a>.
</p>

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

<blockquote>
<pre>
constexpr <i>iterator</i>(<i>iterator</i>&lt;!Const&gt; it)
  requires Const &amp;&amp;
           (convertible_to&lt;iterator_t&lt;Views&gt;, iterator_t&lt;const Views&gt;&gt; &amp;&amp; ...);
</pre>
<blockquote>
<p>
<ins>-?- <i>Preconditions</i>: <code>it.<i>it_</i>.valueless_by_exception()</code> is <code>false</code>.</ins>
<p/>
-8- <i>Effects</i>: Initializes <code><i>parent_</i></code> with <code>it.<i>parent_</i></code>, and let <code><i>i</i></code> be
<code>it.<i>it_</i>.index()</code>, initializes <code><i>it_</i></code> with 
<code><i>base-iter</i>(in_place_index&lt;<i>i</i>&gt;, std::get&lt;<i>i</i>&gt;(std::move(it.<i>it_</i>)))</code>.
</p>
</blockquote>
</blockquote>
</li>

</ol>





<hr>
<h3 id="4082"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4082">4082</a>. <code>views::concat(r)</code> is well-formed when <code>r</code> is an <code>output_range</code></h3>
<p><b>Section:</b> 26.7.18.1 <a href="https://wg21.link/range.concat.overview">[range.concat.overview]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2024-04-27 <b>Last modified:</b> 2024-04-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
Currently, <code>views::concat</code> will return <code>views::all(r)</code> when it takes only one argument, 
which only requires that the type of <code>r</code> models <code>viewable_range</code> which includes <code>output_range</code>:
</p>
<blockquote><pre>
std::vector&lt;int&gt; v;
auto r = std::views::counted(std::back_inserter(v), 3);
auto c = std::views::concat(r); // <span style="color:red;font-weight:bolder">well-formed</span>
</pre></blockquote>
<p>
Since <code>concat_view</code> requires all ranges to be <code>input_range</code>, this seems inconsistent. 
We should reject the above just like <code>views::zip_transform</code> still requires <code>F</code> to be 
<code>move_constructible</code> in the case of an empty pack.
</p>

<p><i>[2024-05-08; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after seven votes in favour during reflector poll.
</p>



<p id="res-4082"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</a>.
</p>

<ol>
<li><p>Modify 26.7.18.1 <a href="https://wg21.link/range.concat.overview">[range.concat.overview]</a> as indicated:</p>

<blockquote>
<p>
-2- The name <code>views::concat</code> denotes a customization point object (16.3.3.3.5 <a href="https://wg21.link/customization.point.object">[customization.point.object]</a>).
Given a pack of subexpressions <code>Es...</code>, the expression <code>views::concat(Es...)</code> is expression-equivalent to
</p>
<ol style="list-style-type: none">
<li><p>(2.1) &mdash; <code>views::all(Es...)</code> if <code>Es</code> is a pack with only one element <ins>whose type models 
<code>input_range</code></ins>,</p></li>
<li><p>(2.2) &mdash; otherwise, <code>concat_view(Es...)</code>.</p></li>
</ol>

</blockquote>
</li>

</ol>





<hr>
<h3 id="4083"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4083">4083</a>. <code>views::as_rvalue</code> should reject non-input ranges</h3>
<p><b>Section:</b> 26.7.7.1 <a href="https://wg21.link/range.as.rvalue.overview">[range.as.rvalue.overview]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2024-04-27 <b>Last modified:</b> 2024-04-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View other</b> <a href="https://cplusplus.github.io/LWG/lwg-index-open.html#range.as.rvalue.overview">active issues</a> in [range.as.rvalue.overview].</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#range.as.rvalue.overview">issues</a> in [range.as.rvalue.overview].</p>
<p><b>Discussion:</b></p>
<p>
<code>views::as_rvalue(r)</code> equivalent to <code>views::all(r)</code> when <code>r</code>'s reference and rvalue reference are
of the same type, which means that in this case we only need to check whether the type of <code>r</code> models <code>viewable_range</code>.
<p/>
However, libstdc++'s implementation always requires <code>as_rvalue_view{r}</code> to be valid, which leads to
divergence when <code>r</code> is not an <code>input_range</code> (<a href="https://godbolt.org/z/EbzEsK88Y">demo</a>):
</p>
<blockquote><pre>
#include &lt;ranges&gt;

struct I {
  int operator*();
  using difference_type = int;
  I&amp; operator++();
  void operator++(int);
};

std::ranges::range auto r = std::ranges::subrange{I{}, std::unreachable_sentinel}
                          | std::views::as_rvalue; // <span style="color:red;font-weight:bolder">// well-formed in libc++/MSVC-STL, ill-formed in libstdc++</span>
</pre></blockquote>
<p>
Although this is precisely a bug in libstdc++ that does not conform to the current wording, it is reasonable to
require <code>r</code> to be an <code>input_range</code> to be consistent with the constraints of <code>as_rvalue_view</code>.
</p>

<p><i>[2024-05-08; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after seven votes in favour during reflector poll.
</p>



<p id="res-4083"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</a>.
</p>

<ol>
<li><p>Modify 26.7.7.1 <a href="https://wg21.link/range.as.rvalue.overview">[range.as.rvalue.overview]</a> as indicated:</p>

<blockquote>
<p>
-2- The name <code>views::as_rvalue</code> denotes a range adaptor object (26.7.2 <a href="https://wg21.link/range.adaptor.object">[range.adaptor.object]</a>).
Let <code>E</code> be an expression and let <code>T</code> be <code>decltype((E))</code>. The expression 
<code>views::as_rvalue(E)</code> is expression-equivalent to:
</p>
<ol style="list-style-type: none">
<li><p>(2.1) &mdash; <code>views::all(E)</code> if <ins><code>T</code> models <code>input_range</code> and</ins> 
<code>same_as&lt;range_rvalue_reference_t&lt;T&gt;, range_reference_t&lt;T&gt;&gt;</code> is <code>true</code>.</p></li>
<li><p>(2.2) &mdash; Otherwise, <code>as_rvalue_view(E)</code>.</p></li>
</ol>

</blockquote>
</li>

</ol>





<hr>
<h3 id="4096"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4096">4096</a>. <code>views::iota(views::iota(0))</code> should be rejected</h3>
<p><b>Section:</b> 26.6.4.1 <a href="https://wg21.link/range.iota.overview">[range.iota.overview]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2024-05-08 <b>Last modified:</b> 2024-05-09</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
<code>views::iota(E)</code> literally means incrementing element E endlessly, but 
<code>views::iota(views::iota(0))</code> is currently well-formed due to CTAD,
rejecting such unreasonable spelling seems therefore reasonable.
</p>

<p><i>[2024-06-24; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after seven votes in favour during reflector poll.
</p>



<p id="res-4096"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</a>.
</p>

<ol>

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

<blockquote>
<p>
-1- <code>iota_view</code> generates a sequence of elements by repeatedly incrementing an initial value.
<p/>
-2- The name <code>views::iota</code> denotes a customization point object (16.3.3.3.5 <a href="https://wg21.link/customization.point.object">[customization.point.object]</a>).
Given subexpressions <code>E</code> and <code>F</code>, the expressions <code>views::iota(E)</code> and
<code>views::iota(E, F)</code> are expression-equivalent to 
<code>iota_view<ins>&lt;decay_t&lt;decltype((E))&gt;&gt;</ins>(E)</code> and <code>iota_view(E, F)</code>, 
respectively.
</p>
</blockquote>

</li>
</ol>






<hr>
<h3 id="4098"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4098">4098</a>. <code>views::adjacent&lt;0&gt;</code> should reject non-forward ranges</h3>
<p><b>Section:</b> 26.7.27.1 <a href="https://wg21.link/range.adjacent.overview">[range.adjacent.overview]</a>, 26.7.28.1 <a href="https://wg21.link/range.adjacent.transform.overview">[range.adjacent.transform.overview]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2024-05-10 <b>Last modified:</b> 2024-06-24</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="https://cplusplus.github.io/LWG/lwg-index.html#range.adjacent.overview">issues</a> in [range.adjacent.overview].</p>
<p><b>Discussion:</b></p>
<p>
Following-up LWG <a href="https://cplusplus.github.io/LWG/lwg-active.html#4082" title="views::concat(r) is well-formed when r is an output_range (Status: Tentatively Ready)">4082</a> and LWG <a href="https://cplusplus.github.io/LWG/lwg-active.html#4083" title="views::as_rvalue should reject non-input ranges (Status: Tentatively Ready)">4083</a>, the current wording makes
<code>views::adjacent&lt;0&gt;(r)</code> and <code>views::adjacent_transform&lt;0&gt;(r, [] { return 0; })</code>
well-formed even when <code>r</code> is just an input range or an output range, which seems to be an oversight.
</p>

<p><i>[2024-06-24; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after six votes in favour during reflector poll.
</p>



<p id="res-4098"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</a>.
</p>

<ol>

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

<blockquote>
<p>
-2- The name <code>views::adjacent&lt;N&gt;</code> denotes a range adaptor object
(26.7.2 <a href="https://wg21.link/range.adaptor.object">[range.adaptor.object]</a>). Given a subexpression <code>E</code> and a constant expression
<code>N</code>, the expression <code>views::adjacent&lt;N&gt;(E)</code> is expression-equivalent to
</p>
<ol style="list-style-type:none">
<li>
<p>(2.1) &mdash; <code>((void)E, auto(views::empty&lt;tuple&lt;&gt;&gt;))</code> if
  <code>N</code> is equal to <code>0</code> <ins>and <code>decltype((E))</code> models <code>forward_range</code></ins>,
</p>
</li>
<li>
<p>(2.2) &mdash; otherwise, <code>adjacent_view&lt;views::all_t&lt;decltype((E))&gt;, N&gt;(E)</code>.</p>
</li>
</ol>
</blockquote>

</li>

<li><p>Modify 26.7.28.1 <a href="https://wg21.link/range.adjacent.transform.overview">[range.adjacent.transform.overview]</a> as indicated:</p>

<blockquote>
<p>
-2- The name <code>views::adjacent_transform&lt;N&gt;</code> denotes a range adaptor object
(26.7.2 <a href="https://wg21.link/range.adaptor.object">[range.adaptor.object]</a>). Given subexpressions <code>E</code> and <code>F</code> 
and a constant expression <code>N</code>:
</p>
<ol style="list-style-type:none">
<li>
<p>(2.1) &mdash; If <code>N</code> is equal to <code>0</code> <ins>and <code>decltype((E))</code> 
models <code>forward_range</code></ins>, <code>views::adjacent_transform&lt;N&gt;(E, F)</code>
is expression-equivalent to <code>((void)E, views::zip_transform(F))</code>, except that
the evaluations of <code>E</code> and <code>F</code> are indeterminately sequenced.
</p>
</li>
<li>
<p>(2.2) &mdash; Otherwise, the expression <code>views::adjacent_transform&lt;N&gt;(E, F)</code> is
expression-equivalent to <code>adjacent_transform_view&lt;views::all_t&lt;decltype((E))&gt;, 
decay_t&lt;decltype((F))&gt;, N&gt;(E, F)</code>.
</p>
</li>
</ol>
</blockquote>

</li>
</ol>






<hr>
<h3 id="4105"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4105">4105</a>. <code>ranges::ends_with</code>'s <i>Returns</i> misses difference casting</h3>
<p><b>Section:</b> 27.6.17 <a href="https://wg21.link/alg.ends.with">[alg.ends.with]</a> <b>Status:</b> <a href="https://cplusplus.github.io/LWG/lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2024-05-17 <b>Last modified:</b> 2024-05-19</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>Discussion:</b></p>
<p>
The <i>Returns</i> of the ranges version of <code>ranges::ends_with</code> are specified as
<code>ranges::equal(ranges::drop_view(ranges::ref_view(r1), N1 - N2), r2, ...)</code> which is not quite right
when <code>N2</code> is an integer-class type and <code>N1</code> is an integer type, because in this case
<code>N1 - N2</code> will be an integer-class type which cannot be implicitly converted to the 
<code>difference_type</code> of <code>r1</code> leading to the construction of <code>drop_view</code> 
being ill-formed.
</p>

<p><i>[2024-06-24; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after five votes in favour during reflector poll.
</p>



<p id="res-4105"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</a>.
</p>

<ol>

<li><p>Modify 27.6.17 <a href="https://wg21.link/alg.ends.with">[alg.ends.with]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;input_range R1, input_range R2, class Pred = ranges::equal_to, class Proj1 = identity,
         class Proj2 = identity&gt;
  requires (forward_range&lt;R1&gt; || sized_range&lt;R1&gt;) &amp;&amp;
           (forward_range&lt;R2&gt; || sized_range&lt;R2&gt;) &amp;&amp;
           indirectly_comparable&lt;iterator_t&lt;R1&gt;, iterator_t&lt;R2&gt;, Pred, Proj1, Proj2&gt;
  constexpr bool ranges::ends_with(R1&amp;&amp; r1, R2&amp;&amp; r2, Pred pred = {},
                                   Proj1 proj1 = {}, Proj2 proj2 = {});
</pre>
<blockquote>
<p>
-3- Let <code>N1</code> be <code>ranges::distance(r1)</code> and <code>N2</code> be
<code>ranges::distance(r2)</code>.
<p/>
-4- <i>Returns</i>: <code>false</code> if <code>N1 &lt; N2</code>, otherwise
</p>
<blockquote><pre>
ranges::equal(ranges::drop_view(ranges::ref_view(r1), N1 - <ins>static_cast&lt;decltype(N1)&gt;(</ins>N2<ins>)</ins>), r2, pred, proj1, proj2)
</pre></blockquote>
</blockquote>
</blockquote>

</li>
</ol>





<hr>
<h3 id="4106"><a href="https://cplusplus.github.io/LWG/lwg-active.html#4106">4106</a>. <code>basic_format_args</code> should not be default-constructible</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#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Hewill Kang <b>Opened:</b> 2024-05-17 <b>Last modified:</b> 2024-05-19</p>
<p><b>Priority: </b>Not Prioritized
</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's unclear why <code>basic_format_args</code> originally provided a default constructor and its actual use cases,
all three major libraries declare them as <code>default</code>, which allows value initialization of 
<code>basic_format_args</code> at compile time.
<p/>
This does not fully conform to the current wording as its signature does not have the <code>constexpr</code>
specifier.
<p/>
Additionally, the current wording only initializes the <code>size_</code> member in the default constructor, which
may lead to undefined behavior when copying <code>basic_format_args</code> as uninitialized <code>data_</code> member 
is copied. There is also an implementation divergence (<a href="https://godbolt.org/z/nYEje7zzj">demo</a>):
</p>
<blockquote><pre>
#include &lt;format&gt;
constexpr std::format_args fmt_args; // <span style="color:red;font-weight:bolder">only well-formed in MSVC-STL</span>
</pre></blockquote>
<p>
One option is to add default member initializers for all members and <code>default</code> the default constructor 
to best match the status quo, which guarantees that <code>basic_format_args</code> is <code>constexpr</code>-able.
<p/>
However, given that <code>basic_format_args</code> has different implementation details in the three libraries, 
its actual members may not be <code>size_</code> and <code>data_</code>. It is unnecessary to ensure that all
the internal members are initialized when default-constructed <code>basic_format_args</code>, indicating that not
providing one is reasonable.
<p/>
The proposed solution is to prefer the more aggressive one.
</p>

<p><i>[2024-05-19; Daniel comments]</i></p>

<p>
The here suggested proposal to remove the default constructor implicitly depends on the decision of
LWG <a href="https://cplusplus.github.io/LWG/lwg-active.html#4061" title="Should std::basic_format_context be default-constructible/copyable/movable? (Status: Tentatively Ready)">4061</a> to remove <code>basic_format_context</code>'s default constructor, since its usage
would require that the exposition-only member <code>args_</code> of type <code>basic_format_args&lt;basic_format_context&gt;</code> 
can be default-constructed as well.
</p>

<p><i>[2024-06-24; Reflector poll]</i></p>

<p>
Set status to Tentatively Ready after eight votes in favour during reflector poll.
</p>



<p id="res-4106"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/N4981" title=" Working Draft, Programming Languages — C++">N4981</a>.
</p>

<ol>

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

<blockquote>
<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:
    <del>basic_format_args() noexcept;</del>

    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;
  };
  [&hellip;]
}
</pre>
</blockquote>
[&hellip;]
<pre>
<del>basic_format_args() noexcept;</del>
</pre>
<blockquote>
<p>
<del>-2- <i>Effects</i> Initializes <code>size_</code> with <code>0</code>.</del>
</p>
</blockquote>
</blockquote>

</li>
</ol>





</body>
</html>
