[PATCH] libstdc++: Implement P1789R3: structured bindings for std::integer_sequence

Tim Song t.canens.cpp@gmail.com
Wed Apr 8 02:21:25 GMT 2026


Is this not the unimplemented local constexpr reference part of P2686R4?

On Tue, Apr 7, 2026 at 1:13 AM Tomasz Kaminski <tkaminsk@redhat.com> wrote:

>
>
> On Mon, Apr 6, 2026 at 6:22 PM Ivan Lazaric <ivan.lazaric1@gmail.com>
> wrote:
>
>> I don’t think CWG3135 is sufficient for the template for snippet
>>
>> In following snippets assume type S is basically
>> std::make_index_sequence<1>
>>
>> template for version:
>>
>>   { // version 1
>>     template for (constexpr auto index : S{}) { }
>>   }
>>
>> Desugared through https://eel.is/c++draft/stmt.expand#5.3 :
>>
>>   { // version 2
>>     constexpr auto&& [a] = S{};
>>   }
>>
>> Desugared and trimmed, https://eel.is/c++draft/dcl.struct.bind#1 :
>>
>>   { // version 3
>>     constexpr auto&& foo = S{};
>>   }
>>
>> The last one is not affected by CWG3135, and fails to compile, because
>> the materialized temporary is not constexpr
>> https://godbolt.org/z/s18G5G657
>>
> It seems like we need equivalent of
> https://cplusplus.github.io/CWG/issues/cwg_active.html#3131 but for
> structured binding case.
>
>
>>
>> On Mon, Apr 6, 2026 at 10:35 AM Daniel Krügler <daniel.kruegler@gmail.com>
>> wrote:
>>
>>> Am So., 5. Apr. 2026 um 22:49 Uhr schrieb Ivan Lazaric <
>>> ivan.lazaric1@gmail.com>:
>>>
>>>> Clarifying, I implemented this for myself locally because it was useful
>>>> in some reflection related code. I searched through my email for
>>>> patches for this proposal, but it seems I haven’t been subscribed for
>>>> long
>>>> enough to find yours. It seemed simple enough so I cleaned it up a bit
>>>> and posted.
>>>>
>>>> You seem to have better understanding of the general situation here,
>>>> so IMO it would be better for me to drop the work and let you continue.
>>>> If you wish to use any snippets from what I posted, feel free.
>>>>
>>>> I built locally with Jakubs patch, and the noted failures now pass.
>>>> Something that still fails though, which is explicitly mentioned in
>>>> paper:
>>>>
>>>>     template for (constexpr auto index : std::make_index_sequence<20>{})
>>>>         static_assert( index + 1 ); // error, not a constant expression
>>>>
>>>> Desugared a bit (also fails):
>>>>
>>>>   {
>>>>     constexpr auto&& [a, b, c] = std::make_index_sequence<3>{};
>>>>
>>>>     static_assert( a == 0 );
>>>>     static_assert( b == 1 );
>>>>     static_assert( c == 2 );
>>>>   }
>>>>
>>>> Please verify this, as I could be missing some patches
>>>>
>>> This is CWG 3135 (
>>> https://cplusplus.github.io/CWG/issues/cwg_active.html#3135), which was
>>> accepted in Croydon, but presumably not yet  implemented in gcc.
>>>
>>> - Daniel
>>>
>>>
>>>>
>>>> On Sun, Apr 5, 2026 at 8:33 PM Matthias Wippich <mfwippich@gmail.com>
>>>> wrote:
>>>>
>>>>> >Will post an updated patch, but wouldn’t pre-CWG3135 wording also
>>>>> work, due to lifetime extension?
>>>>> Without the changes from cwg3135, this cannot interact well with p2686
>>>>> constexpr structured bindings. The non-constexpr case should be fine.
>>>>> That's very unfortunate since the intended use is with p2686 constexpr
>>>>> bindings + p1061 pack-introducing bindings - therefore, implementing
>>>>> p1789 without first addressing cwg3135 seems moot to me.
>>>>>
>>>>> As Tomasz mentioned, I already submitted a patch for this end of last
>>>>> year but waited to see whether we fix p1789 by addressing the core
>>>>> language defect or by changing the library specification instead.
>>>>> Since cwg3135 is accepted now, I was going to update it as soon as
>>>>> Jakub's patch for cwg3135 from 2 days ago is merged (so tests pass).
>>>>>
>>>>> Since your patch seems to be in better shape than mine, I do not mind
>>>>> abandoning the previous patch in favor of this one. @Tomasz: Which one
>>>>> do you want to go ahead with? Does the release target change depending
>>>>> on which one is used or is it going to be GCC 17 either way?
>>>>>
>>>>>
>>>>>
>>>>> On Sun, Apr 5, 2026 at 1:38 PM Ivan Lazaric <ivan.lazaric1@gmail.com>
>>>>> wrote:
>>>>> >
>>>>> > https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p1789r3.pdf
>>>>> >
>>>>> > P1789 enables accessing the sequence values through structured
>>>>> bindings.
>>>>> > ```
>>>>> > auto [...values] = std::make_index_sequence<10>{};
>>>>> > // values is a pack of size 10, and elements 0, 1, 2, ..., 9
>>>>> > ```
>>>>> >
>>>>> > Corresponding C++ draft commit:
>>>>> 3d71a838ed2a1689dd329f964ec4d58152487151
>>>>> > Feature-test macro integer_sequence has been bumped to 202511L.
>>>>> >
>>>>> > libstdc++-v3/ChangeLog:
>>>>> >
>>>>> >         * include/bits/utility.h:
>>>>> >         Implement structured bindings protocol for
>>>>> std::integer_sequence.
>>>>> >         * include/bits/version.def: Bump integer_sequence
>>>>> feature-test macro.
>>>>> >         * include/bits/version.h: Regenerate.
>>>>> >         * testsuite/20_util/integer_sequence/structured_binding.cc:
>>>>> New test.
>>>>> >
>>>>> > Signed-off-by: Ivan Lazaric <ivan.lazaric1@gmail.com>
>>>>> > ---
>>>>> > Fixed a missing `std::` on `size_t` , thanks Linaro.
>>>>> > Extended the test.
>>>>> >
>>>>> > Only part that fails is the last block in `test_basic()`
>>>>> > I am pretty sure that's because of:
>>>>> > ```
>>>>> > static constexpr int&& x = 1;
>>>>> > static_assert(x == 1); // fails, would've worked if it was `const
>>>>> int&&` or `const int&`
>>>>> > ```
>>>>> >
>>>>> > https://godbolt.org/z/jM18sv5nh
>>>>> >
>>>>> >  libstdc++-v3/include/bits/utility.h           | 28 ++++++++
>>>>> >  libstdc++-v3/include/bits/version.def         |  5 ++
>>>>> >  libstdc++-v3/include/bits/version.h           |  7 +-
>>>>> >  .../integer_sequence/structured_binding.cc    | 72
>>>>> +++++++++++++++++++
>>>>> >  4 files changed, 111 insertions(+), 1 deletion(-)
>>>>> >  create mode 100644
>>>>> libstdc++-v3/testsuite/20_util/integer_sequence/structured_binding.cc
>>>>> >
>>>>> > diff --git a/libstdc++-v3/include/bits/utility.h
>>>>> b/libstdc++-v3/include/bits/utility.h
>>>>> > index bd6b18d54dd..159884dd814 100644
>>>>> > --- a/libstdc++-v3/include/bits/utility.h
>>>>> > +++ b/libstdc++-v3/include/bits/utility.h
>>>>> > @@ -150,6 +150,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
>>>>> >        static constexpr size_t size() noexcept { return
>>>>> sizeof...(_Idx); }
>>>>> >      };
>>>>> >
>>>>> > +#if __glibcxx_integer_sequence >= 202511L // C++ >= 26
>>>>> > +    template<typename _Tp, _Tp... _Idx>
>>>>> > +      struct tuple_size<integer_sequence<_Tp, _Idx...>>
>>>>> > +      : integral_constant<size_t, sizeof...(_Idx)> { };
>>>>> > +
>>>>> > +    template<size_t __i, class _Tp, _Tp... _Idx>
>>>>> > +      struct tuple_element<__i, integer_sequence<_Tp, _Idx...>>
>>>>> > +      {
>>>>> > +       static_assert(__i < sizeof...(_Idx));
>>>>> > +       using type = _Tp;
>>>>> > +      };
>>>>> > +
>>>>> > +    template<size_t __i, class _Tp, _Tp... _Idx>
>>>>> > +      struct tuple_element<__i, const integer_sequence<_Tp,
>>>>> _Idx...>>
>>>>> > +      {
>>>>> > +       static_assert(__i < sizeof...(_Idx));
>>>>> > +       using type = _Tp;
>>>>> > +      };
>>>>> > +
>>>>> > +    template<size_t __i, class _Tp, _Tp... _Idx>
>>>>> > +      constexpr _Tp
>>>>> > +      get (integer_sequence<_Tp, _Idx...>) noexcept
>>>>> > +      {
>>>>> > +       static_assert(__i < sizeof...(_Idx));
>>>>> > +       return _Idx...[__i];
>>>>> > +      }
>>>>> > +#endif // __glibcxx_integer_sequence >= 202511L
>>>>> > +
>>>>> >    /// Alias template make_integer_sequence
>>>>> >    template<typename _Tp, _Tp _Num>
>>>>> >      using make_integer_sequence
>>>>> > diff --git a/libstdc++-v3/include/bits/version.def
>>>>> b/libstdc++-v3/include/bits/version.def
>>>>> > index 1265f01757c..81ec5723844 100644
>>>>> > --- a/libstdc++-v3/include/bits/version.def
>>>>> > +++ b/libstdc++-v3/include/bits/version.def
>>>>> > @@ -184,6 +184,11 @@ ftms = {
>>>>> >
>>>>> >  ftms = {
>>>>> >    name = integer_sequence;
>>>>> > +  values = {
>>>>> > +    v = 202511;
>>>>> > +    cxxmin = 26;
>>>>> > +    extra_cond = "__cpp_pack_indexing";
>>>>> > +  };
>>>>> >    values = {
>>>>> >      v = 201304;
>>>>> >      cxxmin = 14;
>>>>> > diff --git a/libstdc++-v3/include/bits/version.h
>>>>> b/libstdc++-v3/include/bits/version.h
>>>>> > index 00f352089f7..cde4fa839db 100644
>>>>> > --- a/libstdc++-v3/include/bits/version.h
>>>>> > +++ b/libstdc++-v3/include/bits/version.h
>>>>> > @@ -186,7 +186,12 @@
>>>>> >  #undef __glibcxx_want_exchange_function
>>>>> >
>>>>> >  #if !defined(__cpp_lib_integer_sequence)
>>>>> > -# if (__cplusplus >= 201402L)
>>>>> > +# if (__cplusplus >  202302L) && (__cpp_pack_indexing)
>>>>> > +#  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/structured_binding.cc
>>>>> b/libstdc++-v3/testsuite/20_util/integer_sequence/structured_binding.cc
>>>>> > new file mode 100644
>>>>> > index 00000000000..18cbcae53e5
>>>>> > --- /dev/null
>>>>> > +++
>>>>> b/libstdc++-v3/testsuite/20_util/integer_sequence/structured_binding.cc
>>>>> > @@ -0,0 +1,72 @@
>>>>> > +// { dg-do compile { target c++26 } }
>>>>> > +
>>>>> > +#include <utility>
>>>>> > +#include <testsuite_hooks.h>
>>>>> > +
>>>>> > +#if __cpp_lib_integer_sequence < 202511L
>>>>> > +# error "Feature-test macro __cpp_lib_integer_sequence is incorrect"
>>>>> > +#endif
>>>>> > +
>>>>> > +constexpr auto
>>>>> > +destructure_sum(auto seq)
>>>>> > +{
>>>>> > +  auto [...elems] = seq;
>>>>> > +  return (0 + ... + elems);
>>>>> > +}
>>>>> > +
>>>>> > +using IS1 = std::make_index_sequence<10>;
>>>>> > +static_assert( std::tuple_size_v<IS1> == 10 );
>>>>> > +static_assert( std::is_same_v<std::tuple_element_t<3, IS1>,
>>>>> std::size_t> );
>>>>> > +static_assert( std::get<7>(IS1{}) == 7 );
>>>>> > +static_assert( destructure_sum(IS1{}) == 45 );
>>>>> > +
>>>>> > +using IS2 = std::integer_sequence<int, 42, 101, -13>;
>>>>> > +static_assert( std::tuple_size_v<IS2> == 3 );
>>>>> > +static_assert( std::is_same_v<std::tuple_element_t<1, IS2>, int> );
>>>>> > +static_assert( std::get<2>(IS2{}) == -13 );
>>>>> > +static_assert( destructure_sum(IS2{}) == 130 );
>>>>> > +
>>>>> > +using IS3 = std::integer_sequence<char>;
>>>>> > +static_assert( std::tuple_size_v<IS3> == 0 );
>>>>> > +
>>>>> > +template<typename = void>
>>>>> > +constexpr bool
>>>>> > +test_basic()
>>>>> > +{
>>>>> > +  {
>>>>> > +    auto [...elems] = std::make_index_sequence<10>{};
>>>>> > +
>>>>> > +    static_assert( sizeof...(elems) == 10 );
>>>>> > +
>>>>> > +    VERIFY( elems...[0] == 0 );
>>>>> > +    VERIFY( elems...[3] == 3 );
>>>>> > +    VERIFY( elems...[9] == 9 );
>>>>> > +  }
>>>>> > +
>>>>> > +  {
>>>>> > +    auto [...elems] = std::integer_sequence<int, 3, 5, 7, 11>{};
>>>>> > +
>>>>> > +    static_assert( sizeof...(elems) == 4 );
>>>>> > +
>>>>> > +    VERIFY( elems...[0] == 3 );
>>>>> > +    VERIFY( elems...[1] == 5 );
>>>>> > +    VERIFY( elems...[2] == 7 );
>>>>> > +    VERIFY( elems...[3] == 11 );
>>>>> > +  }
>>>>> > +
>>>>> > +  {
>>>>> > +    static constexpr auto [...elems] = std::integer_sequence<short,
>>>>> 2, 4, 8, 16>{};
>>>>> > +
>>>>> > +    static_assert( sizeof...(elems) == 4 );
>>>>> > +
>>>>> > +    // these fail
>>>>> > +    static_assert( elems...[0] == 2 );
>>>>> > +    static_assert( elems...[1] == 4 );
>>>>> > +    static_assert( elems...[2] == 8 );
>>>>> > +    static_assert( elems...[3] == 16 );
>>>>> > +  }
>>>>> > +
>>>>> > +  return true;
>>>>> > +}
>>>>> > +
>>>>> > +static_assert( test_basic() );
>>>>> > --
>>>>> > 2.43.0
>>>>> >
>>>>>
>>>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/libstdc++/attachments/20260407/1ac795cd/attachment-0001.htm>


More information about the Libstdc++ mailing list