C++ Library Extensions 2022.12.09
To help learn modern C++ programming
31-visit.cpp
Go to the documentation of this file.
1#include <tpf_output.hpp>
2
5
6namespace tpf::types
7{
8 template<typename Type>
9 struct is_pair_type_st
10 {
11 static constexpr bool value = false;
12 };
13
14 template<typename Type_1, typename Type_2>
15 struct is_pair_type_st<std::pair<Type_1, Type_2>>
16 {
17 static constexpr bool value = true;
18 };
19
20 template<typename Type>
21 constexpr bool is_pair_type_v = is_pair_type_st<remove_cv_ref_t<Type>>::value;
22
23 template<typename Type>
24 struct is_pair_of_variant_type_st
25 {
26 static constexpr bool value = false;
27 };
28
29 template<typename KeyType, typename... Types>
30 struct is_pair_of_variant_type_st<std::pair<KeyType, std::variant<Types...>>>
31 {
32 static constexpr bool value = true;
33 };
34
35 template<typename Type>
36 constexpr bool is_pair_of_variant_type_v =
38
39 template<typename Type>
41 {
42 static constexpr bool value = false;
43 };
44
45 template<typename... Types>
46 struct is_variant_type_st<std::variant<Types...>>
47 {
48 static constexpr bool value = true;
49 };
50
51 template<typename Type>
52 constexpr bool is_variant_type_v = is_variant_type_st<remove_cv_ref_t<Type>>::value;
53
54 template<typename Type, typename ReturnType = void>
55 using enable_if_pair_t = std::enable_if_t<is_pair_type_v<Type>, ReturnType>;
56
57 template<typename Type, typename ReturnType = void>
58 using enable_if_pair_of_variant_t = std::enable_if_t<is_pair_of_variant_type_v<Type>, ReturnType>;
59
60 template<typename Type, typename ReturnType = void>
61 using enable_if_variant_t = std::enable_if_t<is_variant_type_v<Type>, ReturnType>;
62
63 template<size_t StartIndex, size_t EndIndex>
64 struct compile_time_loop
65 {
66 // this function is enabled only when VariantType is std::variant<Types...>
67 template<typename VisitorType, typename VariantType>
68 static enable_if_variant_t<VariantType>
69 visit_variant(VisitorType&& visitor, VariantType&& vt)
70 {
71 if constexpr(StartIndex < EndIndex)
72 {
73 if(auto ptr = std::get_if<StartIndex>(&vt))
74 {
75 // auto& visit = std::get<StartIndex>(visitor.m_visitors); visit(*ptr);
76 std::get<StartIndex>(visitor.m_visitors)(*ptr);
77 return;
78 }
79 }
80
81 if constexpr (StartIndex + 1 < EndIndex)
82 {
84 visit_variant(std::forward<VisitorType>(visitor) , std::forward<VariantType>(vt));
85 }
86 }
87
88 // this function is enabled only when PairType is std::pair<Type_1, Type_2>
89 template<typename VisitorType, typename PairType>
91 visit_variant(VisitorType&& visitor, PairType&& pair)
92 {
93 if constexpr(StartIndex < EndIndex)
94 {
95 auto& [key, vt] = std::forward<PairType>(pair);
96
97 if(auto ptr = std::get_if<StartIndex>(&vt))
98 {
99 // auto& visit = std::get<StartIndex>(visitor.m_visitors); visit(*ptr);
100 std::get<StartIndex>(visitor.m_visitors)(key, *ptr);
101 return;
102 }
103 }
104
105 if constexpr (StartIndex + 1 < EndIndex)
106 {
108 visit_variant(std::forward<VisitorType>(visitor) , std::forward<PairType>(pair));
109 }
110 }
111
112 }; // end of struct compile_time_loop
113
114 // this function is enabled only when VariantType is std::variant<Types...>
115 template<typename VisitorType, typename VariantType>
116 enable_if_variant_t<VariantType>
117 visit(VisitorType&& visitor, VariantType&& vt)
118 {
119 using variant_t = remove_cv_ref_t<VariantType>;
120 // cppreference.com - std::variant_size_v
121 // https://en.cppreference.com/w/cpp/utility/variant/variant_size
122 constexpr size_t VariantSize = std::variant_size_v<variant_t>;
123
124 compile_time_loop<0, VariantSize>:: template
125 visit_variant(std::forward<VisitorType>(visitor), std::forward<VariantType>(vt));
126 }
127
128 // this function is enabled only when PairType is std::pair<Type_1, Type_2>
129 template<typename VisitorType, typename PairType>
130 enable_if_pair_of_variant_t<PairType>
131 visit(VisitorType&& visitor, PairType&& pair)
132 {
133 using pair_t = remove_cv_ref_t<PairType>;
134 using variant_t = typename pair_t::second_type;
135
136 // cppreference.com - std::variant_size_v
137 // https://en.cppreference.com/w/cpp/utility/variant/variant_size
138 constexpr size_t VariantSize = std::variant_size_v<variant_t>;
139
140 compile_time_loop<0, VariantSize>:: template
141 visit_variant(std::forward<VisitorType>(visitor), std::forward<PairType>(pair));
142 }
143
144 template<typename... VisitorTypes>
145 struct overloaded
146 {
147 using vistors_t = std::tuple<VisitorTypes...>;
148
150
151 overloaded(VisitorTypes... visitors):
152 m_visitors{ std::move(visitors)...} { }
153
154 template<typename ContainerType>
155 void for_each(ContainerType&& container)
156 {
157 for(decltype(auto) vt:
158 std::forward<ContainerType>(container))
159 {
160 types::visit(*this, vt);
161 }
162 }
163
164 template<typename VariantType>
166 operator()(VariantType&& vt)
167 {
168 types::visit(*this, std::forward<VariantType>(vt));
169 }
170
171 template<typename PairType>
173 operator()(PairType&& pvt)
174 {
175 types::visit(*this, std::forward<PairType>(pvt));
176 }
177 };
178
179 // template argument deduction guide
180 // this feature was introduced to C++17 Standards
181 template<typename... VisitorTypes>
182 overloaded(VisitorTypes...) -> overloaded<VisitorTypes...>;
183
184 template<typename... VisitorTypes>
185 overloaded<remove_cv_ref_t<VisitorTypes>...>
186 make_overloaded(VisitorTypes&&... visitors)
187 {
188 return { std::forward<VisitorTypes>(visitors)... };
189 }
190
191} // end of namespace tpf::types
192
193namespace types = tpf::types;
194
196{
197 using name_t = const char*;
198 using age_t = int;
199 using weight_t = double;
200 using variant_t = std::variant<name_t, age_t, weight_t>;
201
202 using container_t = std::vector<variant_t>;
203
204 container_t info;
205
206 info.emplace_back("Thomas Kim");
207 info.emplace_back(30);
208 info.emplace_back(60.5);
209 info.emplace_back("Sophie Turner");
210 info.emplace_back(20);
211 info.emplace_back(56.7);
212
214 auto endl = tpf::endl;
215
217 (
218 [&stream, &endl](auto& name)
219 {
220 stream <<"Name is " << name << endl;
221 },
222
223 [&stream, &endl](auto& age)
224 {
225 stream <<"Age is " << age << endl;
226 },
227
228 [&stream, &endl](auto& weight)
229 {
230 stream << "Weight is " << weight << endl;
231 }
232
233 ).for_each(info);
234
235 stream << endl;
236}
237
239{
240 using key_t = const char*;
241 using name_t = const char*;
242 using age_t = int;
243 using weight_t = double;
244 using variant_t = std::variant<name_t, age_t, weight_t>;
245
246 using container_t = std::map<key_t, variant_t>;
247
248 container_t info;
249
250 info["Programmer"] = "Thomas Kim";
251 info["Age"] = 30;
252 info["Weight"] = 60.5;
253 info["Actress"] = "Sophie Turner";
254 info["Her age"] = 20;
255 info["Her weight"] = 56.7;
256
258 auto endl = tpf::endl;
259
261 (
262 [&stream, &endl](auto&& key, auto&& name)
263 {
264 stream << key << " is " << name << endl;
265 },
266
267 [&stream, &endl](auto&& key, auto&& age)
268 {
269 stream << key << " is " << age << endl;
270 },
271
272 [&stream, &endl](auto&& key, auto&& weight)
273 {
274 stream << key << " is " << weight << endl;
275 }
276 ).for_each(info);
277
278 stream << endl;
279}
280
282{
283 using name_t = const char*;
284 using age_t = int;
285 using weight_t = double;
286
287 using inner_vt_t = std::variant<name_t, weight_t>;
288
289 using variant_t = std::variant<name_t, age_t, weight_t, inner_vt_t>;
290
291 using container_t = std::vector<variant_t>;
292
293 container_t info;
294
295 info.emplace_back("Thomas Kim");
296 info.emplace_back(30);
297 info.emplace_back(60.5);
298 info.emplace_back("Sophie Turner");
299 info.emplace_back(20);
300 info.emplace_back(56.7);
301 info.emplace_back(inner_vt_t{ "James Dean"} );
302 info.emplace_back(inner_vt_t{ 65.6 } );
303 info.emplace_back("Sophie Kim");
304
306 auto endl = tpf::endl;
307
309 (
310 [&stream, &endl](auto& name)
311 {
312 stream <<"Name is " << name << endl;
313 },
314
315 [&stream, &endl](auto& age)
316 {
317 stream <<"Age is " << age << endl;
318 },
319
320 [&stream, &endl](auto& weight)
321 {
322 stream << "Weight is " << weight << endl;
323 },
324
325 [&stream, &endl](auto& vt) // inner_vt_t
326 {
328 (
329 [&stream, &endl](auto&& name)
330 {
331 stream << "Inner Name is " << name << endl;
332 },
333
334 [&stream, &endl](auto&& weight)
335 {
336 stream << "Inner Weight is " << weight << endl;
337 }
338
339 )(std::forward<decltype(vt)>(vt));
340 }
341
342 ).for_each(info);
343
344 stream << endl;
345}
346
348{
349 using key_t = const char*;
350 using name_t = const char*;
351 using age_t = int;
352 using weight_t = double;
353
354 using map_t = std::map<key_t, name_t>;
355
357
358 using variant_t = std::variant<name_t, age_t, weight_t, map_t, map_vt_t>;
359
360 using container_t = std::map<key_t, variant_t>;
361
362 container_t info;
363
364 info["Programmer"] = "Thomas Kim";
365 info["Age"] = 30;
366 info["Weight"] = 60.5;
367 info["Actress"] = "Sophie Turner";
368 info["Her age"] = 20;
369 info["Her weight"] = 56.7;
370 info["Map of Map"] = map_t{ {"Friend", "James Dean"}, {"Buddy", "Albert Kim"} };
371 info["Map of Variants"] = map_vt_t{ {"Friend's Age", 30}, {"Buddy's Weight", 56.7} };
372
374 auto endl = tpf::endl;
375
377 (
378 [&stream, &endl](auto&& key, auto&& name)
379 {
380 stream << key << " is " << name << endl;
381 },
382
383 [&stream, &endl](auto&& key, auto&& age)
384 {
385 stream << key << " is " << age << endl;
386 },
387
388 [&stream, &endl](auto&& key, auto&& weight)
389 {
390 stream << key << " is " << weight << endl;
391 },
392
393 [&stream, &endl](auto&& key, auto&& map) // map_t
394 {
395 for(auto& m: map)
396 {
397 auto& [inner_key, value] = m;
398
399 stream << "Outer Key - " << key
400 << ", inner_key: " << inner_key
401 <<", value: " << value << endl;
402 }
403 },
404
405 [&stream, &endl](auto&& key, auto&& map_vt) // map_vt_t
406 {
408 (
409 [&stream, &endl, &key](auto&& inner_key, auto&& age)
410 {
411 stream << "Outer key: " << key
412 << ", inner_key: " << inner_key<<", age: " << age << endl;
413 },
414
415 [&stream, &endl, &key](auto&& inner_key, auto&& weight)
416 {
417 stream << "Outer key: " << key
418 << ", inner_key: " << inner_key<<", weight: " << weight << endl;
419 }
420
421 ).for_each(std::forward<decltype(map_vt)>(map_vt));
422 }
423
424 ).for_each(info);
425
426 stream << endl;
427}
428
429
430int main()
431{
432 // test_visit_simplified();
433
434 // test_visit_simplified_map();
435
436 // test_visit_variant_of_variants();
437
439}
std::remove_cv_t< std::remove_reference_t< Type > > remove_cv_ref_t
void test_visit_simplified_map()
Definition: 31-visit.cpp:296
tpf::sstream stream
Definition: 31-visit.cpp:3
auto endl
Definition: 31-visit.cpp:4
void test_visit_simplified()
Definition: 31-visit.cpp:196
int main()
Definition: 31-visit.cpp:340
void test_visit_map_of_variants_of_map()
Definition: 31-visit.cpp:347
void test_visit_variant_of_variants()
Definition: 31-visit.cpp:281
Type to string name conversions are defined.
Definition: 31-visit.cpp:7
hidden::map_of_variants_t< KeyType, ElementTypes... > map_of_variants_t
Definition: tpf_types.hpp:6645
std::enable_if_t< is_variant_type_v< Type >, ReturnType > enable_if_variant_t
Definition: 31-visit.cpp:62
std::enable_if_t< is_pair_type_v< Type >, ReturnType > enable_if_pair_t
Definition: 31-visit.cpp:56
overloaded< remove_cv_ref_t< VisitorTypes >... > make_overloaded(VisitorTypes &&... visitors)
Definition: 31-visit.cpp:186
constexpr bool is_variant_type_v
Definition: 31-visit.cpp:53
enable_if_variant_t< VariantType > visit(VisitorType &&visitor, VariantType &&vt)
Definition: 31-visit.cpp:118
overloaded(VisitorTypes...) -> overloaded< VisitorTypes... >
constexpr bool is_pair_of_variant_type_v
Definition: 31-visit.cpp:38
std::enable_if_t< is_pair_of_variant_type_v< Type >, ReturnType > enable_if_pair_of_variant_t
Definition: 31-visit.cpp:59
constexpr bool is_pair_type_v
Definition: 31-visit.cpp:21
std::enable_if_t< is_pair_of_variant_v< remove_cv_ref_t< PairType > > > visit_variant(VisitorType &&visit, PairType &&vpr)
Definition: tpf_types.hpp:7740
std::remove_cv_t< std::remove_reference_t< Type > > remove_cv_ref_t
Remove const volatile reference from Type.
Definition: tpf_types.hpp:151
constexpr auto endl
Definition: tpf_output.hpp:973
static enable_if_pair_of_variant_t< PairType > visit_variant(VisitorType &&visitor, PairType &&pair)
Definition: 31-visit.cpp:91
static enable_if_variant_t< VariantType > visit_variant(VisitorType &&visitor, VariantType &&vt)
Definition: 31-visit.cpp:69
static constexpr bool value
Definition: 31-visit.cpp:11
static constexpr bool value
Definition: 31-visit.cpp:43
void for_each(ContainerType &&container)
Definition: 31-visit.cpp:155
enable_if_variant_t< VariantType > operator()(VariantType &&vt)
Definition: 31-visit.cpp:166
std::tuple< VisitorTypes... > vistors_t
Definition: 31-visit.cpp:148
enable_if_pair_of_variant_t< PairType > operator()(PairType &&pvt)
Definition: 31-visit.cpp:173
overloaded(VisitorTypes... visitors)
Definition: 31-visit.cpp:151
Stream output operators << are implemented.