Skip to content

Commit d9f0b80

Browse files
committed
feat: C++26 pack indexing applied to type_list
Resolves #610
1 parent 4f6b3d9 commit d9f0b80

File tree

1 file changed

+37
-0
lines changed

1 file changed

+37
-0
lines changed

src/core/include/mp-units/bits/type_list.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,25 @@ using type_list_map = type_list_map_impl<From, To>::type;
7272

7373

7474
// element
75+
#ifdef __cpp_pack_indexing
76+
77+
// C++26: Pack indexing (P2662) gives a compiler-native O(1) element access,
78+
// eliminating the indexed_type_list multiple-inheritance machinery entirely.
79+
template<typename List, std::size_t I>
80+
struct type_list_element_impl;
81+
82+
template<template<typename...> typename List, typename... Types, std::size_t I>
83+
struct type_list_element_impl<List<Types...>, I> {
84+
using type = Types...[I];
85+
};
86+
87+
template<TypeList List, std::size_t I>
88+
using type_list_element = type_list_element_impl<List, I>::type;
89+
90+
#else
91+
92+
// C++20/23: Use the "indexed" multiple-inheritance trick to avoid O(N) recursive
93+
// instantiation depth. The compiler resolves the correct leaf via overload resolution.
7594
template<std::size_t I, typename T>
7695
struct type_list_leaf {
7796
using type = T;
@@ -95,6 +114,8 @@ using type_list_element_indexed = typename decltype(type_list_element_func<I>(st
95114
template<TypeList List, std::size_t I>
96115
using type_list_element = type_list_element_indexed<type_list_map<List, indexed_type_list>, I>;
97116

117+
#endif
118+
98119
// front
99120
template<typename List>
100121
struct type_list_front_impl;
@@ -153,13 +174,29 @@ using type_list_join = type_list_join_impl<Lists...>::type;
153174
template<typename List, typename First, typename Second>
154175
struct type_list_split_impl;
155176

177+
static_assert(__cpp_pack_indexing);
178+
179+
#ifdef __cpp_pack_indexing
180+
181+
// C++26: Direct pack indexing avoids building an indexed_type_list (N base classes)
182+
// and then re-traversing it for every element of both output lists.
183+
template<template<typename...> typename List, typename... Args, std::size_t... First, std::size_t... Second>
184+
struct type_list_split_impl<List<Args...>, std::index_sequence<First...>, std::index_sequence<Second...>> {
185+
using first_list = List<Args...[First]...>;
186+
using second_list = List<Args...[sizeof...(First) + Second]...>;
187+
};
188+
189+
#else
190+
156191
template<template<typename...> typename List, typename... Args, std::size_t... First, std::size_t... Second>
157192
struct type_list_split_impl<List<Args...>, std::index_sequence<First...>, std::index_sequence<Second...>> {
158193
using indexed_list = indexed_type_list<Args...>;
159194
using first_list = List<type_list_element_indexed<indexed_list, First>...>;
160195
using second_list = List<type_list_element_indexed<indexed_list, sizeof...(First) + Second>...>;
161196
};
162197

198+
#endif
199+
163200
template<TypeList List, std::size_t N>
164201
requires(N <= type_list_size<List>)
165202
struct type_list_split :

0 commit comments

Comments
 (0)