[gcc r16-8556] libstdc++: Remove span constructor from initializer_list.

Tomasz Kaminski tkaminsk@gcc.gnu.org
Fri Apr 10 06:06:42 GMT 2026


https://gcc.gnu.org/g:bd29a35496cf377c98bebdc3b3a9d8bc2772009b

commit r16-8556-gbd29a35496cf377c98bebdc3b3a9d8bc2772009b
Author: Tomasz Kamiński <tkaminsk@redhat.com>
Date:   Wed Apr 8 17:29:07 2026 +0200

    libstdc++: Remove span constructor from initializer_list.
    
    Following LWG4520 resolution from paper
    P4144R1 Remove span’s initializer_list constructor for C++26.
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/version.def (span_initializer_list): Remove.
            * include/bits/version.h: Regenerate.
            * include/std/span (span::span(initializer_list<value_type>)):
            Remove.
            * testsuite/23_containers/span/init_list_cons.cc: Removed.
            * testsuite/23_containers/span/init_list_cons_neg.cc: Removed.
            * testsuite/23_containers/inplace_vector/copy.cc: Replace span
            with initializer_list in eq helper.
            * testsuite/23_containers/inplace_vector/erasure.cc: Likewise.
            * testsuite/23_containers/inplace_vector/move.cc: Likewise.
    
    Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
    Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>

Diff:
---
 libstdc++-v3/include/bits/version.def              |  8 ---
 libstdc++-v3/include/bits/version.h                | 10 ----
 libstdc++-v3/include/std/span                      | 16 +-----
 .../testsuite/23_containers/inplace_vector/copy.cc |  2 +-
 .../23_containers/inplace_vector/erasure.cc        | 11 +---
 .../testsuite/23_containers/inplace_vector/move.cc |  2 +-
 .../testsuite/23_containers/span/init_list_cons.cc | 65 ----------------------
 .../23_containers/span/init_list_cons_neg.cc       | 36 ------------
 8 files changed, 6 insertions(+), 144 deletions(-)

diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 9a3b3655974c..059c38c6c13d 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -2171,14 +2171,6 @@ ftms = {
   };
 };
 
-ftms = {
-  name = span_initializer_list;
-  values = {
-    v = 202311;
-    cxxmin = 26;
-  };
-};
-
 ftms = {
   name = text_encoding;
   values = {
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 8f541fc389ec..f806e8f3f9c0 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -2426,16 +2426,6 @@
 #endif /* !defined(__cpp_lib_saturation_arithmetic) */
 #undef __glibcxx_want_saturation_arithmetic
 
-#if !defined(__cpp_lib_span_initializer_list)
-# if (__cplusplus >  202302L)
-#  define __glibcxx_span_initializer_list 202311L
-#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_span_initializer_list)
-#   define __cpp_lib_span_initializer_list 202311L
-#  endif
-# endif
-#endif /* !defined(__cpp_lib_span_initializer_list) */
-#undef __glibcxx_want_span_initializer_list
-
 #if !defined(__cpp_lib_text_encoding)
 # if (__cplusplus >  202302L) && _GLIBCXX_HOSTED && (_GLIBCXX_USE_NL_LANGINFO_L)
 #  define __glibcxx_text_encoding 202306L
diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span
index a2f338449c8a..a5f5bf48f90e 100644
--- a/libstdc++-v3/include/std/span
+++ b/libstdc++-v3/include/std/span
@@ -47,9 +47,7 @@
 #include <cstddef>
 #include <bits/stl_iterator.h>
 #include <bits/ranges_base.h>
-#ifdef __cpp_lib_span_initializer_list
-# include <initializer_list>
-#endif
+
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 _GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -232,18 +230,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	: _M_ptr(ranges::data(__range)), _M_extent(ranges::size(__range))
 	{ }
 
-#if __cpp_lib_span_initializer_list >= 202311L // >= C++26
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Winit-list-lifetime"
-      constexpr
-      explicit(extent != dynamic_extent)
-      span(initializer_list<value_type> __il)
-      requires (is_const_v<_Type>)
-      : _M_ptr(__il.begin()), _M_extent(__il.size())
-      { }
-#pragma GCC diagnostic pop
-#endif
-
       constexpr
       span(const span&) noexcept = default;
 
diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc
index 917eebd80f7c..11260c63313c 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/copy.cc
@@ -138,7 +138,7 @@ static_assert(std::is_trivially_copy_assignable_v<std::inplace_vector<Z, 0>>);
 
 template<typename T, size_t N>
 constexpr bool
-eq(const std::inplace_vector<T, N>& s, std::span<const T> o)
+eq(const std::inplace_vector<T, N>& s, std::initializer_list<std::type_identity_t<T>> o)
 { return std::ranges::equal(s, o); }
 
 constexpr void
diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc
index 8fb56e906234..a019dc0a1f15 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/erasure.cc
@@ -1,18 +1,13 @@
 // { dg-do run { target c++26 } }
 
 #include <inplace_vector>
+#include <ranges>
 #include <testsuite_hooks.h>
-#include <span>
 
 template<typename T, size_t N>
 constexpr bool
-eq(const std::inplace_vector<T, N>& l, std::span<const T> r) {
-  if (l.size() != r.size())
-    return false;
-  for (auto i = 0u; i < l.size(); ++i)
-    if (l[i] != r[i])
-      return false;
-  return true;
+eq(const std::inplace_vector<T, N>& l, std::initializer_list<std::type_identity_t<T>> r) {
+  return std::ranges::equal(l, r);
 };
 
 constexpr void
diff --git a/libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc b/libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc
index e8703e027fe3..8b5c3e9f247f 100644
--- a/libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc
+++ b/libstdc++-v3/testsuite/23_containers/inplace_vector/move.cc
@@ -177,7 +177,7 @@ static_assert(std::is_nothrow_swappable_v<std::inplace_vector<Z, 0>>);
 
 template<typename T, size_t N>
 constexpr bool
-eq(const std::inplace_vector<T, N>& s, std::span<const T> o)
+eq(const std::inplace_vector<T, N>& s, std::initializer_list<std::type_identity_t<T>> o)
 { return std::ranges::equal(s, o); }
 
 constexpr void
diff --git a/libstdc++-v3/testsuite/23_containers/span/init_list_cons.cc b/libstdc++-v3/testsuite/23_containers/span/init_list_cons.cc
deleted file mode 100644
index 1dc30ab1a50b..000000000000
--- a/libstdc++-v3/testsuite/23_containers/span/init_list_cons.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-// { dg-do compile { target c++26 } }
-
-#include <span>
-#include <type_traits>
-
-#if !defined(__cpp_lib_span_initializer_list)
-# error "__cpp_lib_span_initializer_list should be defined"
-#elif __cpp_lib_span_initializer_list < 202311L
-# error "Wrong value for __cpp_lib_span_initializer_list (should be >= 202311L)"
-#endif
-
-// Check the constraint on the initializer_list constructor
-static_assert( std::is_const_v<std::span<const int>::element_type>);
-static_assert(!std::is_const_v<std::span<      int>::element_type>);
-
-static_assert( std::is_constructible_v<std::span<const int    >, std::initializer_list<      int>>);
-static_assert( std::is_constructible_v<std::span<const int    >, std::initializer_list<const int>>);
-static_assert( std::is_constructible_v<std::span<const int, 42>, std::initializer_list<      int>>);
-static_assert( std::is_constructible_v<std::span<const int, 42>, std::initializer_list<const int>>);
-static_assert(!std::is_constructible_v<std::span<      int    >, std::initializer_list<      int>>);
-static_assert(!std::is_constructible_v<std::span<      int    >, std::initializer_list<const int>>);
-static_assert(!std::is_constructible_v<std::span<      int, 42>, std::initializer_list<      int>>);
-static_assert(!std::is_constructible_v<std::span<      int, 42>, std::initializer_list<const int>>);
-
-// Check the explicit-ness on the initializer_list constructor
-static_assert( std::is_convertible_v<std::initializer_list<      int>, std::span<const int    >>);
-static_assert( std::is_convertible_v<std::initializer_list<const int>, std::span<const int    >>);
-static_assert(!std::is_convertible_v<std::initializer_list<      int>, std::span<const int, 42>>);
-static_assert(!std::is_convertible_v<std::initializer_list<const int>, std::span<const int, 42>>);
-static_assert(!std::is_convertible_v<std::initializer_list<      int>, std::span<      int    >>);
-static_assert(!std::is_convertible_v<std::initializer_list<const int>, std::span<      int    >>);
-static_assert(!std::is_convertible_v<std::initializer_list<      int>, std::span<      int, 42>>);
-static_assert(!std::is_convertible_v<std::initializer_list<const int>, std::span<      int, 42>>);
-
-constexpr size_t fun1(std::span<const int> s)
-{
-  return s.size();
-}
-
-static_assert(fun1({}) == 0);
-static_assert(fun1({1, 2, 3}) == 3);
-static_assert(fun1(std::initializer_list<int>{1, 2, 3}) == 3);
-
-// Stress-test array->pointer decays
-struct decayer {
-  constexpr decayer() = default;
-  constexpr decayer(decayer *) {}
-};
-
-constexpr size_t fun2(std::span<const decayer> s)
-{
-  return s.size();
-}
-
-void test01()
-{
-  int intArray[42];
-  static_assert(fun1(intArray) == 42);
-
-  decayer decArray[42];
-  static_assert(fun2(decArray) == 42);
-  static_assert(fun2({decArray}) == 1); // decayer[] -> decayer* -> decayer(decayer*) -> init_list<decayer> of 1 element
-  static_assert(fun2({decArray, decArray + 42}) == 2); // does not select span(iterator, iterator)
-  static_assert(fun2({decArray, decArray, decArray}) == 3);
-}
diff --git a/libstdc++-v3/testsuite/23_containers/span/init_list_cons_neg.cc b/libstdc++-v3/testsuite/23_containers/span/init_list_cons_neg.cc
deleted file mode 100644
index 6b78156ad5df..000000000000
--- a/libstdc++-v3/testsuite/23_containers/span/init_list_cons_neg.cc
+++ /dev/null
@@ -1,36 +0,0 @@
-// { dg-do run { target { c++20 && c++23_down } } }
-// { dg-do compile { target c++26 } }
-
-#include <span>
-#include <utility>
-
-#include <testsuite_hooks.h>
-
-struct Any {
-  constexpr Any() { }
-  template<typename T> constexpr Any(T) { }
-};
-
-// Examples from P2447R4
-void one(std::pair<int, int>) {}
-void one(std::span<const int>) {}
-void two(std::span<const int, 2>) {}
-constexpr std::size_t three(std::span<void * const> v) { return v.size(); }
-constexpr std::size_t four(std::span<const Any> v) { return v.size(); }
-
-void *array3[10];
-Any array4[10];
-
-int main()
-{
-  one({1, 2}); // { dg-error "call of overloaded" "should be ambiguous with the one(std::pair) overload" { target c++26 } }
-  two({{1, 2}}); // { dg-error "would use explicit constructor" "should prefer the initializer_list constructor, which is explicit" { target c++26 } }
-
-#if __cpp_lib_span_initializer_list
-  static_assert(three({array3, 0}) == 2);
-  static_assert(four({array4, array4 + 10}) == 2);
-#else
-  static_assert(three({array3, 0}) == 0);
-  static_assert(four({array4, array4 + 10}) == 10);
-#endif
-}


More information about the Libstdc++-cvs mailing list