ugmisc 0.2
Miscellaneous C++ header library
Loading...
Searching...
No Matches
typelist.hpp
Go to the documentation of this file.
1/*
2 * SPDX-Licence-Identifier: MIT
3 *
4 * Copyright 2025 Larry Chips
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the “Software”), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#pragma once
25
26#include <type_traits>
27
28
58
59
60
61
62namespace ugmisc {
63
64
69template<class...T> struct type_list;
70
71
72
73
74namespace typelist_ {
75
76
77template<class...T> struct type_list_common {
78 static constexpr std::size_t size = sizeof...(T);
79
80 template<template<class...> class Templ> using apply = Templ<T...>;
81
82 template<class...U>
83 using prepend = type_list<U..., T...>;
84
85 template<class...U>
86 using append = type_list<T..., U...>;
87};
88
89
90} /* typelist_ */
91
92
93
94
95template<> struct type_list<> : public typelist_::type_list_common<> {
96};
97
98
99template<class T1, class...Ts> struct type_list<T1, Ts...>
100: public typelist_::type_list_common<T1, Ts...>
101{
102};
103
104
105
106template<std::size_t I, class T> struct get_type_list_member {};
107
108
109
110template<std::size_t I, class T1, class...T>
111struct get_type_list_member<I, type_list<T1, T...>> {
112 static_assert( I < sizeof...(T) + 1, "Index out of range" );
113 using type = typename get_type_list_member<I-1, type_list<T...>>::type;
114};
115
116template<class T1, class...T> struct get_type_list_member<0, type_list<T1, T...>> {
117 using type = T1;
118};
119
120template<std::size_t I, class T> using type_list_member =
121 typename get_type_list_member<I, T>::type;
122
123
124
125
126
127
128template<class T> struct is_type_list : public std::false_type {};
129
130template<class...T> struct is_type_list<type_list<T...>> : std::true_type {};
131
132template<class T> static constexpr bool is_type_list_v = is_type_list<T>::value;
133
134
135template<class...T> static constexpr bool are_type_lists_v = (... && is_type_list_v<T>);
136
137
138
139
140template<class...> struct concatenate_type_lists;
141
142
143template<> struct concatenate_type_lists<> {
144 using type = type_list<>;
145};
146
147
148template<class...T> struct concatenate_type_lists<type_list<T...>> {
149 using type = type_list<T...>;
150};
151
152
153template<class T1, class T2, class T3, class...Ts> struct concatenate_type_lists<T1, T2, T3, Ts...> {
154 static_assert( are_type_lists_v<T1, T2, T3, Ts...> );
155 using type = typename concatenate_type_lists<
156 typename concatenate_type_lists<T1, T2>::type,
157 typename concatenate_type_lists<T3, Ts...>::type
158 >::type;
159};
160
161
162template<class T, class...Ts>
163struct concatenate_type_lists< T, type_list<Ts...> >
164{
165 static_assert( is_type_list_v<T> );
166 using type = typename T::template append<Ts...>;
167};
168
169
193template<class...T>
194using concatenate_type_lists_t = typename concatenate_type_lists<T...>::type;
195
196
197
198
199template<std::size_t From, std::size_t To, class T> struct get_type_list_slice;
200
201template<std::size_t From, class...T>
202struct get_type_list_slice<From, From, type_list<T...>> {
203 static_assert( From <= sizeof...(T) );
204 using type = type_list<>;
205};
206
207template<std::size_t From, class...T>
208struct get_type_list_slice<From, From+1, type_list<T...>> {
209 static_assert( From < sizeof...(T) );
210 using type =
211 type_list< typename get_type_list_member<From, type_list<T...>>::type >;
212};
213
214template<std::size_t From, std::size_t To, class...T>
215struct get_type_list_slice<From, To, type_list<T...>> {
216private:
217 static_assert( To >= From, "Invalid range: To must be no less than From." );
218 static_assert( To > From+1, "Logic error. Wrong partial specialisation." );
219
220 using list = type_list<T...>;
221
222 static constexpr std::size_t from1 = From;
223 static constexpr std::size_t to1 = From + (To - From)/2;
224 static constexpr std::size_t from2 = to1;
225 static constexpr std::size_t to2 = To;
226
227 using part1 = typename get_type_list_slice<from1, to1, list>::type;
228 using part2 = typename get_type_list_slice<from2, to2, list>::type;
229
230public:
231 using type = concatenate_type_lists_t< part1, part2 >;
232};
233
234
235
236
246template<class T> struct wrapped_list;
247
248
249template<class...T> struct wrapped_list<type_list<T...>> {
250 using type = type_list<T...>;
251};
252
253
254template<class T> struct wrapped_list<wrapped_list<T>> {
255 using type = wrapped_list<T>;
256};
257
258
259
260
261template<class T> struct get_as_list {
262 using type = type_list<T>;
263};
264
265
266template<class...T> struct get_as_list<type_list<T...>> {
267 using type = type_list<T...>;
268};
269
270
271template<class T> using get_as_list_t = typename get_as_list<T>::type;
272
273
274template<class T> struct unwrap {
275 using type = T;
276};
277
278
279template<class T> struct unwrap<wrapped_list<T>> {
280 using type = T;
281};
282
283
306template<class...T> struct flatten {
307 // Every flatten special defs a type_list type. The generic one
308 // concatenates the lists created from each tparam.
310};
311
312
313/*
314 * A single type which is not a type_list or wrapped_list is simply put into a
315 * type_list.
316 */
317template<class T> struct flatten<T> {
318 using type = type_list<T>;
319};
320
321
322/*
323 * A type list needs unwrapping recursively, so we flatten each of the member
324 * types.
325 */
326template<class...T> struct flatten< type_list<T...> > {
327 using type = concatenate_type_lists_t<typename flatten<T>::type...>;
328};
329
330
331/*
332 * A wrapped_list is unwrapped once, then the content put into a list.
333 */
334template<class T> struct flatten< wrapped_list<T> > {
335 using type = type_list<T>; // Note the lack of recursion here.
336};
337
338
339template<class...T> using flatten_t = typename flatten<T...>::type;
340
341
342
343
352template<std::size_t From, std::size_t To, class T>
353using type_list_slice = typename get_type_list_slice<From, To, T>::type;
354
358template<std::size_t From, std::size_t Count, class T>
360
367template<std::size_t Count, class T>
369
376template<std::size_t Count, class T>
377using type_list_suffix = type_list_slice<T::size - Count, T::size, T>;
378
385template<std::size_t Count, class T>
387
394template<std::size_t Count, class T>
395using type_list_remove_suffix = type_list_slice<0, T::size-Count, T>;
396
397
404template<std::size_t From, std::size_t To, class...T>
405using flatten_slice = type_list_slice<From, To, flatten_t<T...>>;
406
410template<std::size_t From, std::size_t Count, class...T>
411using flatten_sized_slice = type_list_sized_slice<From, Count, flatten_t<T...>>;
412
416template<std::size_t Count, class...T>
417using flatten_prefix = type_list_prefix<Count, flatten_t<T...>>;
418
422template<std::size_t Count, class...T>
423using flatten_suffix = type_list_suffix<Count, flatten_t<T...>>;
424
431template<std::size_t Count, class...T>
432using flatten_remove_prefix = type_list_remove_prefix<Count, flatten_t<T...>>;
433
440template<std::size_t Count, class...T>
441using flatten_remove_suffix = type_list_remove_suffix<Count, flatten_t<T...>>;
442
443} /* ::ugmisc */
Converts the template parameters into a type_list.
Definition typelist.hpp:306
Definition typelist.hpp:69
Definition typelist.hpp:246
type_list_slice< T::size - Count, T::size, T > type_list_suffix
Definition typelist.hpp:377
type_list_sized_slice< From, Count, flatten_t< T... > > flatten_sized_slice
Definition typelist.hpp:411
type_list_remove_prefix< Count, flatten_t< T... > > flatten_remove_prefix
Definition typelist.hpp:432
type_list_slice< From, To, flatten_t< T... > > flatten_slice
Definition typelist.hpp:405
type_list_prefix< Count, flatten_t< T... > > flatten_prefix
Definition typelist.hpp:417
type_list_slice< From, From+Count, T > type_list_sized_slice
Definition typelist.hpp:359
type_list_slice< 0, Count, T > type_list_prefix
Definition typelist.hpp:368
type_list_slice< Count, T::size, T > type_list_remove_prefix
Definition typelist.hpp:386
typename get_type_list_slice< From, To, T >::type type_list_slice
Definition typelist.hpp:353
type_list_remove_suffix< Count, flatten_t< T... > > flatten_remove_suffix
Definition typelist.hpp:441
typename concatenate_type_lists< T... >::type concatenate_type_lists_t
Definition typelist.hpp:194
type_list_slice< 0, T::size-Count, T > type_list_remove_suffix
Definition typelist.hpp:395
type_list_suffix< Count, flatten_t< T... > > flatten_suffix
Definition typelist.hpp:423