UgMisc 0.3
Miscellaneous C++ header library
Loading...
Searching...
No Matches
typelist.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: © 2026 Larry Chips <larry@larrychips.net>
3 * SPDX-Licence-Identifier: MIT
4 */
12#include "samples_output.hpp"
14
15#include <ugmisc/typelist.hpp>
16
17#include <iostream>
18#include <variant>
19#include <string>
20#include <tuple>
21#include <type_traits>
22#include <utility>
23
24
25using namespace ugmisc;
26
27
28/*
29 * Later, in main(), we will print the expected output of each function call
30 * after the call itself, and that will be much easier and more legible if the
31 * types are represented by known names that we can write directly.
32 *
33 * Compare
34 *
35 * expect << typeid(Cat).name() << "\n";
36 *
37 * to
38 *
39 * expect << "Cat\n";
40 *
41 * sTypeName will be found and returned by getTypeName<Type>().
42 */
43#define TYPE(name) \
44 struct name { \
45 static const char * const sTypeName; \
46 }; \
47 const char * const name::sTypeName = #name
48
49TYPE(Lion);
50TYPE(Siamese);
51TYPE(Car);
52TYPE(Van);
53
54TYPE(Lions);
55TYPE(Siameeses);
56TYPE(Cars);
57TYPE(Vans);
58
59
60template<typename T>
61struct PluraliseBase {
62 static std::string sTypeName() {
63 return std::string("Pluralise<") + getTypeName<T>() + ">";
64 }
65};
66
67template<typename T>
68struct Pluralise;
69
70template<>
71struct Pluralise<Lion> : public PluraliseBase<Lion> {
72 using type = Lions;
73};
74
75template<>
76struct Pluralise<Siamese> : public PluraliseBase<Siamese> {
77 using type = Siameeses;
78};
79
80template<>
81struct Pluralise<Car> : public PluraliseBase<Car> {
82 using type = Cars;
83};
84
85template<>
86struct Pluralise<Van> : public PluraliseBase<Van> {
87 using type = Vans;
88};
89
90
91using Cats = type_list<Lion, Siamese>;
92using Vehicles = type_list<Car, Van>;
94
95using CatsVariant = Cats::apply_t<std::variant>;
96using VehiclesTuple = Vehicles::apply_t<std::tuple>;
97
100
101
102template<class T>
103struct is_cat : public std::false_type {};
104
105template<>
106struct is_cat<Lion> : public std::true_type {};
107
108template<>
109struct is_cat<Siamese> : public std::true_type {};
110
111
112using CatsFromAll = type_list_filter<is_cat, All>;
114using CatsFromVarious = flatten_filter<
115 is_cat,
117 Lion,
119 Van
120 >;
121
122using Backward = type_list_stride<-1, -1, All::size, All>;
123
124
125template<class T, class...Extras>
126static void print(const char *name, Extras...extras) {
127 SampleOutput out;
128 TypesPrinter printer{out};
129 /*
130 * The name is explicitly passed in via the macro anyway, so there is no
131 * point separately expecting it later.
132 */
133 out.always() << name << ":\n";
134 printer.print<T>();
135 [[maybe_unused]] auto& _out = (out << ... << extras);
136}
137
138#define PRINT_LAST(...) print<__VA_ARGS__>(#__VA_ARGS__)
139#define PRINT(...) print<__VA_ARGS__>(#__VA_ARGS__, "\n")
140
141int main(int, char**) {
142 auto expect = SampleOutput().expect();
143 auto always = SampleOutput().always();
144
145 PRINT(Cats);
146 expect << "type_list\n" " Lion Siamese\n"
147 "\n";
148
149 PRINT(Vehicles);
150 expect << "type_list\n" " Car Van\n"
151 "\n";
152
153 PRINT(All);
154 expect << "type_list\n" " Lion Siamese Car Van\n"
155 "\n";
156
157 PRINT(CatsVariant);
158 expect << "variant\n" " Lion Siamese\n"
159 "\n";
160
161 PRINT(VehiclesTuple);
162 expect << "tuple\n" " Car Van\n"
163 "\n";
164
165 PRINT(CatsFromAll);
166 expect << "type_list\n" " Lion Siamese\n"
167 "\n";
168
169 PRINT(AllButCats);
170 expect << "type_list\n" " Car Van\n"
171 "\n";
172
173 PRINT(CatsFromVarious);
174 expect << "type_list\n" " Lion Siamese\n"
175 "\n";
176
177 PRINT(Plurals);
178 expect << "type_list\n" " Lions Siameeses Cars Vans\n"
179 "\n";
180
181 PRINT(Pluralisers);
182 expect << "type_list\n"
183 " Pluralise<Lion> Pluralise<Siamese> Pluralise<Car> Pluralise<Van>\n"
184 "\n";
185
186 PRINT(Backward);
187 expect << "type_list\n"
188 " Van Car Siamese Lion\n"
189 "\n";
190
191 PRINT(All::stride_t<0, 2, 2>);
192 expect << "type_list\n"
193 " Lion Car\n"
194 "\n";
195
196 always << "\nResults of using the type_list methods and operators:\n\n";
197
198 type_list<Lion> lion;
199 type_list<Siamese> siamese;
200
201 PRINT( decltype(lion.append(siamese)) );
202 expect << "type_list\n"
203 " Lion Siamese\n"
204 "\n";
205
206 PRINT( decltype(lion + siamese) );
207 expect << "type_list\n"
208 " Lion Siamese\n"
209 "\n";
210
211 // Stride can be represented by an integer_sequence.
212 // Base 0, stride 2, count 2.
213 std::integer_sequence<int, 0, 2, 2> stride_args;
214
215 // Stride can be represented by integral_constants.
216 std::integral_constant<int, 0> base;
217 std::integral_constant<int, 2> stride;
218 std::integral_constant<int, 2> count;
219
220 All all;
221
222 PRINT( decltype(all.stride(stride_args)) );
223 expect << "type_list\n"
224 " Lion Car\n"
225 "\n";
226
227 PRINT_LAST( decltype(all.stride(base, stride, count)) );
228 expect << "type_list\n"
229 " Lion Car\n";
230
231 return 0;
232}
Encapsulates a list of types.
Definition typelist.hpp:860
static constexpr append_t< U... > append(type_list< U... >)
Definition typelist.hpp:959
Lists of types which may be used in some of the ugmisc templates where a single type would usually be...
typename typelist_::type_list_stride< Base, Stride, Count, T >::type type_list_stride
Definition typelist.hpp:493
typename typelist_::apply_each< F, T >::class_types type_list_apply_each_class
Definition typelist.hpp:390
type_list_filter< Test, flatten_t< T... >, Mod > flatten_filter
Definition typelist.hpp:432
typename typelist_::filter_type_list< Test, T, Mod >::type type_list_filter
Definition typelist.hpp:365
@ no_invert_test
Keep types when the Filter returns true.
Definition typelist.hpp:92
typename typelist_::apply_each< F, T >::inner_types type_list_apply_each
Definition typelist.hpp:400
typename concatenate_type_lists< T... >::type concatenate_type_lists_t
Definition typelist.hpp:173