Skip to content

Commit 749904d

Browse files
committed
DPL: use C++26 extension to expand packs where available
O(1) in both CPU and time rather than O(N) when compiling the pack expansion. Removes the limit to 100 elements in a struct. Requires XCode 26.4
1 parent 2a2edee commit 749904d

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

Framework/Foundation/include/Framework/StructToTuple.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
177217
template <bool B = false, class T, int D = nested_brace_constructible_size<B, T>() / 10, typename L>
178218
requires(D == 9)
179219
constexpr 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+
376418
template <int D, typename T, typename L>
377419
constexpr auto homogeneous_apply_refs_sized(L l, T&& object)
378420
{

0 commit comments

Comments
 (0)