@@ -174,6 +174,46 @@ consteval int nested_brace_constructible_size()
174174 return brace_constructible_size<type>() - nesting;
175175}
176176
177+ // Structured binding packs (P1061) are C++26, but clang implements them as an
178+ // extension in every language mode and advertises them via the feature test
179+ // macro, so we can use them while still compiling as C++20.
180+ #if defined(__cpp_structured_bindings) && __cpp_structured_bindings >= 202411L
181+ #define DPL_STRUCTURED_BINDING_PACKS 1
182+ #endif
183+
184+ #ifdef DPL_STRUCTURED_BINDING_PACKS
185+ namespace detail
186+ {
187+ template <typename ... Ts>
188+ struct first_type ;
189+ template <typename First, typename ... Rest>
190+ struct first_type <First, Rest...> {
191+ using type = First;
192+ };
193+ template <typename ... Ts>
194+ using first_t = typename first_type<Ts...>::type;
195+ } // namespace detail
196+
197+ #ifdef __clang__
198+ #pragma clang diagnostic push
199+ #pragma clang diagnostic ignored "-Wc++26-extensions"
200+ #endif
201+ template <bool B = false , class T , int D = 0 , typename L>
202+ constexpr auto homogeneous_apply_refs (L l, T&& object)
203+ {
204+ auto && [...members ] = object;
205+ if constexpr (sizeof ...(members) == 0 ) {
206+ return std::array<bool , 0 >();
207+ } else {
208+ return std::array<detail::first_t <decltype (l (members))...>, sizeof ...(members)>{l (members)...};
209+ }
210+ }
211+ #ifdef __clang__
212+ #pragma clang diagnostic pop
213+ #endif
214+
215+ #else // DPL_STRUCTURED_BINDING_PACKS
216+
177217template <bool B = false , class T , int D = nested_brace_constructible_size<B, T>() / 10 , typename L>
178218 requires (D == 9 )
179219constexpr auto homogeneous_apply_refs(L l, T&& object)
@@ -373,6 +413,8 @@ constexpr auto homogeneous_apply_refs(L l, T&& object)
373413 // clang-format on
374414}
375415
416+ #endif // DPL_STRUCTURED_BINDING_PACKS
417+
376418template <int D, typename T, typename L>
377419constexpr auto homogeneous_apply_refs_sized (L l, T&& object)
378420{
0 commit comments