<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 4293: span::subspan/first/last chooses wrong constructor when T is const-qualified bool</title>
<meta property="og:title" content="Issue 4293: span::subspan/first/last chooses wrong constructor when T is const-qualified bool">
<meta property="og:description" content="C++ library issue. Status: Tentatively Ready">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue4293.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#Ready">Tentatively Ready</a> status.</em></p>
<h3 id="4293"><a href="lwg-active.html#4293">4293</a>. span::subspan/first/last chooses wrong constructor when T is const-qualified bool</h3>
<p><b>Section:</b> 23.7.2.2.4 <a href="https://wg21.link/span.sub">[span.sub]</a> <b>Status:</b> <a href="lwg-active.html#Ready">Tentatively Ready</a>
 <b>Submitter:</b> Yuhan Liu <b>Opened:</b> 2025-07-11 <b>Last modified:</b> 2025-08-26</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all other</b> <a href="lwg-index.html#span.sub">issues</a> in [span.sub].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#Tentatively Ready">Tentatively Ready</a> status.</p>
<p><b>Discussion:</b></p>
<p>
In section 23.7.2.2.4 <a href="https://wg21.link/span.sub">[span.sub]</a>, paragraphs p12, p14, and p16 erroneously
use the initializer list constructor for span instead of the intended
iterator/count constructor.
</p>
<p>
Specifically, in these paragraphs, the standard states:
<blockquote>
<i>Effects</i>: Equivalent to: <code class='backtick'>return {data(), count};</code>
</blockquote>
or some variant of <code class='backtick'>return {pointer, size}</code>.  As reported in
<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120997">GCC bug 120997</a>
this results in a span that points to invalid stack memory.
This can be reproduced on GCC 15.1 for subspan, first, and last:
<a href="https://godbolt.org/z/r9nrdWscq">https://godbolt.org/z/r9nrdWscq</a>.
</p>
<p>
A proposed fix (thanks to Jonathan Wakely) could look like this following:
<blockquote>
<code>return span&lt;element_type&gt;(data(), count);</code>
</blockquote>
for the affected paragraphs,
which would explicitly specify the constructor used.
</p>

<p><i>[2025-07-11; Jonathan adds proposed resolution]</i></p>

<p>
The meaning of those <i>Effects</i>: paragraphs was changed for C++26 by
<a href="https://wg21.link/P2447R6" title=" std::span over an initializer list">P2447R6</a> which added the <code class='backtick'>span(initializer_list)</code> constructor.
A simpler demo is:
<blockquote><pre><code>bool a[5]{};
std::span&lt;const bool&gt; s(a);
std::span&lt;const bool&gt; s2 = s.first(5);
assert(s2.size() == 5); // OK in C++23, fails in C++26
assert(s2.data() == a); // OK in C++23, fails in C++26
</code></pre></blockquote>
The proposed resolution is to use <code class='backtick'>R(data(), count)</code> instead of
<code class='backtick'>{data(), count}</code>. The former always (uniformly) means the same thing,
but for the latter the meaning of list-initialization depends on the types.
The list-initialization form will choose the initializer-list constructor
when <code class='backtick'>data()</code> and <code class='backtick'>count</code> are both convertible to the element type.
</p>

<p><i>[2025-08-21; Reflector poll]</i></p>

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



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

<ol>

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

<blockquote>

<pre><code>
template&lt;size_t Count&gt; constexpr span&lt;element_type, Count&gt; first() const;
</code></pre>
<blockquote>
<p>-1- <i>Mandates</i>: <code>Count &lt;= Extent</code> is <code class='backtick'>true</code>.</p>
<p>-2- <i>Hardened preconditions</i>: <code>Count &lt;= size()</code> is <code class='backtick'>true</code>.</p>
<p>-3- <i>Effects</i>: Equivalent to:
<code>return R<ins>(</ins><del>{</del>data(), Count<del>}</del><ins>)</ins>;</code>
where <code class='backtick'>R</code> is the return type.
</p>
</blockquote>

<pre><code>
template&lt;size_t Count&gt; constexpr span&lt;element_type, Count&gt; last() const;
</code></pre>
<blockquote>
<p>-4- <i>Mandates</i>: <code>Count &lt;= Extent</code> is <code class='backtick'>true</code>.</p>
<p>-5- <i>Hardened preconditions</i>: <code>Count &lt;= size()</code> is <code class='backtick'>true</code>.</p>
<p>-6- <i>Effects</i>: Equivalent to:
<code>return R<ins>(</ins><del>{</del>data() + (size() - Count), Count<del>}</del><ins>)</ins>;</code>
where <code class='backtick'>R</code> is the return type.
</p>
</blockquote>

<pre><code>
template&lt;size_t Offset, size_t Count = dynamic_extent&gt;
  constexpr span&lt;element_type, <i>see below</i>&gt; subspan() const;
</code></pre>
<blockquote>
<p>-7- <i>Mandates</i>:
<blockquote><pre><code>Offset &lt;= Extent &amp;&amp; (Count == dynamic_extent || Count &lt;= Extent - Offset)
</code></pre></blockquote>
is <code class='backtick'>true</code>.</p>
<p>-8- <i>Hardened preconditions</i>:
<blockquote><pre><code>Offset &lt;= size() &amp;&amp; (Count == dynamic_extent || Count &lt;= size() - Offset)
</code></pre></blockquote>
is <code class='backtick'>true</code>.</p>
<p>-9- <i>Effects</i>: Equivalent to:
<blockquote><pre><code>return span&lt;ElementType, <i>see below</i>&gt;(
    data() + Offset, Count != dynamic_extent ? Count : size() - Offset);
</code></pre></blockquote>
</p>
<p>-10- <i>Remarks</i>:
The second template argument of the returned <code class='backtick'>span</code> type is:
<blockquote><pre><code>Count != dynamic_extent ? Count
                        : (Extent != dynamic_extent ? Extent - Offset
                                                    : dynamic_extent)
</code></pre></blockquote>
</p>
</blockquote>

<pre><code>
constexpr span&lt;element_type, dynamic_extent&gt; first(size_type count) const;
</code></pre>
<blockquote>
<p>-11- <i>Hardened preconditions</i>: <code>count &lt;= size()</code> is <code class='backtick'>true</code>.</p>
<p>-12- <i>Effects</i>: Equivalent to:
<code>return <ins>R(</ins><del>{</del>data(), count<del>}</del><ins>)</ins>;</code>
<ins>where <code class='backtick'>R</code> is the return type</ins>.
</p>
</blockquote>

<pre><code>
constexpr span&lt;element_type, dynamic_extent&gt; last(size_type count) const;
</code></pre>
<blockquote>
<p>-13- <i>Hardened preconditions</i>: <code>count &lt;= size()</code> is <code class='backtick'>true</code>.</p>
<p>-14- <i>Effects</i>: Equivalent to:
<code>return <ins>R(</ins><del>{</del>data() + (size() - count), count<del>}</del><ins>)</ins>;</code>
<ins>where <code class='backtick'>R</code> is the return type</ins>.
</p>
</blockquote>

<pre><code>
constexpr span&lt;element_type, dynamic_extent&gt; subspan(
  size_type offset, size_type count = dynamic_extent) const;
</code></pre>
<blockquote>
<p>-15- <i>Hardened preconditions</i>:
<blockquote><pre><code>offset &lt;= size() &amp;&amp; (count == dynamic_extent || count &lt;= size() - offset
</code></pre></blockquote>
is <code class='backtick'>true</code>.</p>
<p>-16- <i>Effects</i>: Equivalent to:
<blockquote><pre><code>return <ins>R(</ins><del>{</del>data() + offset, count == dynamic_extent ? size() - offset :  count<del>}</del><ins>)</ins>;
</code></pre></blockquote>
<ins>where <code class='backtick'>R</code> is the return type</ins>.
</p>
</blockquote>

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






</body>
</html>
