The attached patch implements P1789R3 by making std::integer_sequence
decomposable. This paper was approved for inclusion in C++26 by LWG motion
14 of the 2025 Kona meeting.

Tested on x86_64-linux locally.
From 0b4a71ef13e220cc17edc2d53c41bafc195d6186 Mon Sep 17 00:00:00 2001
From: Matthias Wippich <[email protected]>
Date: Sun, 9 Nov 2025 00:10:08 +0100
Subject: [PATCH] libstdc++: Implement P1789R3 - Library Support for Expansion
 Statements

libstdc++-v3/ChangeLog:
	* include/bits/utility.h: Make integer_sequence decomposable.
	* include/bits/version.def: Bump __cpp_lib_integer_sequence for C++26.
	* include/bits/version.h: Regenerate.
	* testsuite/20_util/integer_sequence/p1789.cc: New test.

Signed-off-by: Matthias Wippich <[email protected]>
---
 libstdc++-v3/include/bits/utility.h           | 33 ++++++++++++
 libstdc++-v3/include/bits/version.def         |  4 ++
 libstdc++-v3/include/bits/version.h           |  7 ++-
 .../20_util/integer_sequence/p1789.cc         | 53 +++++++++++++++++++
 4 files changed, 96 insertions(+), 1 deletion(-)
 create mode 100644 libstdc++-v3/testsuite/20_util/integer_sequence/p1789.cc

diff --git a/libstdc++-v3/include/bits/utility.h b/libstdc++-v3/include/bits/utility.h
index 96ac69883f1..e1b0e0bd760 100644
--- a/libstdc++-v3/include/bits/utility.h
+++ b/libstdc++-v3/include/bits/utility.h
@@ -170,6 +170,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   /// Alias template index_sequence_for
   template<typename... _Types>
     using index_sequence_for = make_index_sequence<sizeof...(_Types)>;
+
+#if (__glibcxx_integer_sequence >= 202511L) // C++ >= 26
+  /// structured binding support for integer_sequence
+  template <typename _Tp, _Tp... _Num>
+    struct tuple_size<integer_sequence<_Tp, _Num...>>
+    : public integral_constant<size_t, sizeof...(_Num)> { };
+
+  template <size_t _Idx, typename _Tp, _Tp... _Num>
+    struct tuple_element<_Idx, integer_sequence<_Tp, _Num...>>
+    {
+      static_assert(_Idx < sizeof...(_Num), 
+        "integer_sequence index is in range");
+      using type = _Tp;
+    };
+  
+  template <size_t _Idx, typename _Tp, _Tp... _Num>
+    struct tuple_element<_Idx, const integer_sequence<_Tp, _Num...>>
+    {
+      static_assert(_Idx < sizeof...(_Num), 
+        "integer_sequence index is in range");
+      using type = _Tp;
+    };
+
+  template <size_t _Idx, typename _Tp, _Tp... _Num>
+    [[__nodiscard__]]
+    constexpr _Tp 
+    get(integer_sequence<_Tp, _Num...>) noexcept
+    {
+      static_assert(_Idx < sizeof...(_Num), 
+        "integer_sequence index is within bounds");
+      return _Num...[_Idx];
+    }
+#endif // __glibcxx_integer_sequence
 #endif // __glibcxx_integer_sequence
 
 #if __cpp_structured_bindings >= 202411L
diff --git a/libstdc++-v3/include/bits/version.def b/libstdc++-v3/include/bits/version.def
index 29ecf15c7e3..dcd2905b028 100644
--- a/libstdc++-v3/include/bits/version.def
+++ b/libstdc++-v3/include/bits/version.def
@@ -176,6 +176,10 @@ ftms = {
 
 ftms = {
   name = integer_sequence;
+  values = {
+    v = 202511;
+    cxxmin = 26;
+  };
   values = {
     v = 201304;
     cxxmin = 14;
diff --git a/libstdc++-v3/include/bits/version.h b/libstdc++-v3/include/bits/version.h
index 5901d27113d..510b0e6fb58 100644
--- a/libstdc++-v3/include/bits/version.h
+++ b/libstdc++-v3/include/bits/version.h
@@ -176,7 +176,12 @@
 #undef __glibcxx_want_exchange_function
 
 #if !defined(__cpp_lib_integer_sequence)
-# if (__cplusplus >= 201402L)
+# if (__cplusplus >  202302L)
+#  define __glibcxx_integer_sequence 202511L
+#  if defined(__glibcxx_want_all) || defined(__glibcxx_want_integer_sequence)
+#   define __cpp_lib_integer_sequence 202511L
+#  endif
+# elif (__cplusplus >= 201402L)
 #  define __glibcxx_integer_sequence 201304L
 #  if defined(__glibcxx_want_all) || defined(__glibcxx_want_integer_sequence)
 #   define __cpp_lib_integer_sequence 201304L
diff --git a/libstdc++-v3/testsuite/20_util/integer_sequence/p1789.cc b/libstdc++-v3/testsuite/20_util/integer_sequence/p1789.cc
new file mode 100644
index 00000000000..983dfcb58e0
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/integer_sequence/p1789.cc
@@ -0,0 +1,53 @@
+// { dg-do compile { target c++26 } }
+//
+// Copyright (C) 2013-2025 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <type_traits>
+#include <utility>
+
+using std::integer_sequence;
+
+using empty = integer_sequence<int>;
+using size4 = integer_sequence<int, 7, 9, 8, 2>;
+
+static_assert( std::tuple_size_v<empty> == 0, "tuple_size == 0" );
+static_assert( std::tuple_size_v<const empty> == 0, "tuple_size == 0" );
+
+static_assert( std::tuple_size_v<size4> == 4, "tuple_size == 4" );
+static_assert( std::tuple_size_v<const size4> == 4, "tuple_size == 4" );
+
+static_assert( std::is_same_v<std::tuple_element_t<0, size4>, int> , "element type 0 wrong" );
+static_assert( std::is_same_v<std::tuple_element_t<1, size4>, int> , "element type 1 wrong" );
+static_assert( std::is_same_v<std::tuple_element_t<2, size4>, int> , "element type 2 wrong" );
+static_assert( std::is_same_v<std::tuple_element_t<3, size4>, int> , "element type 3 wrong" );
+
+static_assert( std::is_same_v<std::tuple_element_t<0, const size4>, int> , "element type 0 wrong" );
+static_assert( std::is_same_v<std::tuple_element_t<1, const size4>, int> , "element type 1 wrong" );
+static_assert( std::is_same_v<std::tuple_element_t<2, const size4>, int> , "element type 2 wrong" );
+static_assert( std::is_same_v<std::tuple_element_t<3, const size4>, int> , "element type 3 wrong" );
+
+constexpr inline size4 seq4{};
+static_assert( std::get<0>(seq4) == 7 , "element value 0 wrong" );
+static_assert( std::get<1>(seq4) == 9 , "element value 1 wrong" );
+static_assert( std::get<2>(seq4) == 8 , "element value 2 wrong" );
+static_assert( std::get<3>(seq4) == 2 , "element value 3 wrong" );
+
+static_assert( std::is_same_v<std::tuple_element_t<0, empty>, int> , "" ); // { dg-error "here" }
+static_assert( std::is_same_v<std::tuple_element_t<0, const empty>, int> , "" ); // { dg-error "here" }
+
+// { dg-error "static assertion failed" "" { target *-*-* } 0 }
-- 
2.51.2

Reply via email to