ug_misc 0.1
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
70
71
72
73
74namespace ugmisc {
75
76
81template<class...T> struct type_list;
82
83
84
85
86namespace imp_ {
87template<class...T> struct type_list_common {
88 static constexpr std::size_t size = sizeof...(T);
89
90 template<template<class...> class Templ> using apply = Templ<T...>;
91
92 template<class...U>
93 using prepend = type_list<U..., T...>;
94
95 template<class...U>
96 using append = type_list<T..., U...>;
97};
98} /* imp_ */
99
100
101
102
103template<> struct type_list<> : public imp_::type_list_common<> {
104};
105
106
107template<class T1, class...Ts> struct type_list<T1, Ts...>
108: public imp_::type_list_common<T1, Ts...>
109{
110private:
111 template<class, std::size_t I> struct get_indexed_type {
112 using type = typename type_list<Ts...>::indexed_type<I - 1>;
113 };
114
115 template<class T> struct get_indexed_type<T, 0> {
116 using type = T1;
117 };
118
119public:
120 template<std::size_t I> using indexed_type = typename get_indexed_type<void, I>::type;
121};
122
123
124
125template<std::size_t I, class T> struct get_indexed {};
126
127template<std::size_t I, class...T> struct get_indexed<I, type_list<T...>> {
128 using type = typename type_list<T...>::template indexed_type<I>;
129};
130
131template<std::size_t I, class T> using get_indexed_t = typename get_indexed<I, T>::type;
132
133
134template<class T> struct is_type_list : public std::false_type {};
135
136template<class...T> struct is_type_list<type_list<T...>> : std::true_type {};
137
138template<class T> static constexpr bool is_type_list_v = is_type_list<T>::value;
139
140
141template<class...T> static constexpr bool are_type_lists_v = (... && is_type_list_v<T>);
142
143
144
145
146template<class...> struct concatenate_type_lists;
147
148
149template<> struct concatenate_type_lists<> {
150 using type = type_list<>;
151};
152
153
154template<class...T> struct concatenate_type_lists<type_list<T...>> {
155 using type = type_list<T...>;
156};
157
158
159template<class T1, class T2, class T3, class...Ts> struct concatenate_type_lists<T1, T2, T3, Ts...> {
160 static_assert( are_type_lists_v<T1, T2, T3, Ts...> );
161 using type = typename concatenate_type_lists<
162 typename concatenate_type_lists<T1, T2>::type,
163 typename concatenate_type_lists<T3, Ts...>::type
164 >::type;
165};
166
167
168template<class T, class...Ts>
169struct concatenate_type_lists< T, type_list<Ts...> >
170{
171 static_assert( is_type_list_v<T> );
172 using type = typename T::template append<Ts...>;
173};
174
175
199template<class...T>
200using concatenate_type_lists_t = typename concatenate_type_lists<T...>::type;
201
202
203
204
214template<class T> struct wrapped_list;
215
216
217template<class...T> struct wrapped_list<type_list<T...>> {
218 using type = type_list<T...>;
219};
220
221
222template<class T> struct wrapped_list<wrapped_list<T>> {
223 using type = wrapped_list<T>;
224};
225
226
227
228
229template<class T> struct get_as_list {
230 using type = type_list<T>;
231};
232
233
234template<class...T> struct get_as_list<type_list<T...>> {
235 using type = type_list<T...>;
236};
237
238
239template<class T> using get_as_list_t = typename get_as_list<T>::type;
240
241
242template<class T> struct unwrap {
243 using type = T;
244};
245
246
247template<class T> struct unwrap<wrapped_list<T>> {
248 using type = T;
249};
250
251
274template<class...T> struct flatten {
275 // Every flatten special defs a type_list type. The generic one
276 // concatenates the lists created from each tparam.
278};
279
280
281/*
282 * A single type which is not a type_list or wrapped_list is simply put into a
283 * type_list.
284 */
285template<class T> struct flatten<T> {
286 using type = type_list<T>;
287};
288
289
290/*
291 * A type list needs unwrapping recursively, so we flatten each of the member
292 * types.
293 */
294template<class...T> struct flatten< type_list<T...> > {
295 using type = concatenate_type_lists_t<typename flatten<T>::type...>;
296};
297
298
299/*
300 * A wrapped_list is unwrapped once, then the content put into a list.
301 */
302template<class T> struct flatten< wrapped_list<T> > {
303 using type = type_list<T>; // Note the lack of recursion here.
304};
305
306
307template<class...T> using flatten_t = typename flatten<T...>::type;
308
309
310} /* ::ugmisc */
Converts the template parameters into a type_list.
Definition typelist.hpp:274
Definition typelist.hpp:81
Definition typelist.hpp:214
typename concatenate_type_lists< T... >::type concatenate_type_lists_t
Definition typelist.hpp:200