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
