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>
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>
22
24 template<typename Type>
26 {
27 static constexpr bool value = false;
28 };
29
30 template<typename Type, typename... Types>
31 struct is_pair_of_variant_type_st<std::pair<Type, std::variant<Types...>>>
32 {
33 static constexpr bool value = true;
34 };
35
36 template<typename Type>
39
40 template<typename Type>
42 {
43 static constexpr bool value = false;
44 };
45
46 template<typename... Types>
47 struct is_variant_type_st<std::variant<Types...>>
48 {
49 static constexpr bool value = true;
50 };
51
52 template<typename Type>
54
55 template<typename Type, typename ReturnType = void>
56 using enable_if_pair_t = std::enable_if_t<is_pair_type_v<Type>, ReturnType>;
57
58 template<typename Type, typename ReturnType = void>
59 using enable_if_pair_of_variant_t = std::enable_if_t<is_pair_of_variant_type_v<Type>, ReturnType>;
60
61 template<typename Type, typename ReturnType = void>
62 using enable_if_variant_t = std::enable_if_t<is_variant_type_v<Type>, ReturnType>;
63
64 template<size_t StartIndex, size_t EndIndex>
66 {
67 // this function is enabled only when VariantType is std::variant<Types...>
68 template<typename VisitorType, typename VariantType>
70 visit_variant(VisitorType&& visitor, VariantType&& vt)
71 {
72 if constexpr(StartIndex < EndIndex)
73 {
74 if(auto ptr = std::get_if<StartIndex>(&vt))
75 {
76 // auto& visit = std::get<StartIndex>(visitor.m_visitors); visit(*ptr);
77 std::get<StartIndex>(visitor.m_visitors)(*ptr);
78 return;
79 }
80 }
81
82 if constexpr (StartIndex + 1 < EndIndex)
83 {
85 visit_variant(std::forward<VisitorType>(visitor) , std::forward<VariantType>(vt));
86 }
87 }
88
89 // this function is enabled only when PairType is std::pair<Type_1, Type_2>
90 template<typename VisitorType, typename PairType>
92 visit_variant(VisitorType&& visitor, PairType&& pair)
93 {
94 if constexpr(StartIndex < EndIndex)
95 {
96 auto& [key, vt] = std::forward<PairType>(pair);
97
98 if(auto ptr = std::get_if<StartIndex>(&vt))
99 {
100 // auto& visit = std::get<StartIndex>(visitor.m_visitors); visit(*ptr);
101 std::get<StartIndex>(visitor.m_visitors)(key, *ptr);
102 return;
103 }
104 }
105
106 if constexpr (StartIndex + 1 < EndIndex)
107 {
109 visit_variant(std::forward<VisitorType>(visitor) , std::forward<PairType>(pair));
110 }
111 }
112
113 }; // end of struct compile_time_loop
114
115 // this function is enabled only when VariantType is std::variant<Types...>
116 template<typename VisitorType, typename VariantType>
117 enable_if_variant_t<VariantType>
118 visit(VisitorType&& visitor, VariantType&& vt)
119 {
120 using variant_t = remove_cv_ref_t<VariantType>;
121 // cppreference.com - std::variant_size_v
122 // https://en.cppreference.com/w/cpp/utility/variant/variant_size
123 constexpr size_t VariantSize = std::variant_size_v<variant_t>;
124
126 visit_variant(std::forward<VisitorType>(visitor), std::forward<VariantType>(vt));
127 }
128
129 // this function is enabled only when PairType is std::pair<Type_1, Type_2>
130 template<typename VisitorType, typename PairType>
131 enable_if_pair_of_variant_t<PairType>
132 visit(VisitorType&& visitor, PairType&& pair)
133 {
134 using pair_t = remove_cv_ref_t<PairType>;
135 using variant_t = typename pair_t::second_type;
136
137 // cppreference.com - std::variant_size_v
138 // https://en.cppreference.com/w/cpp/utility/variant/variant_size
139 constexpr size_t VariantSize = std::variant_size_v<variant_t>;
140
142 visit_variant(std::forward<VisitorType>(visitor), std::forward<PairType>(pair));
143 }
144
145 template<typename... VisitorTypes>
147 {
148 using vistors_t = std::tuple<VisitorTypes...>;
149
151
152 overloaded(VisitorTypes... visitors):
153 m_visitors{ std::move(visitors)...} { }
154
155 template<typename ContainerType>
156 void for_each(ContainerType&& container)
157 {
158 for(decltype(auto) vt:
159 std::forward<ContainerType>(container))
160 {
161 types::visit(*this, vt);
162 }
163 }
164
165 template<typename VariantType>
167 operator()(VariantType&& vt) const
168 {
169 types::visit(*this, std::forward<VariantType>(vt));
170 }
171
172 template<typename PairType>
174 operator()(PairType&& vt)
175 {
176 types::visit(*this, std::forward<PairType>(vt));
177 }
178 };
179
180 // template argument deduction guide
181 // this feature was introduced to C++17 Standards
182 template<typename... VisitorTypes>
183 overloaded(VisitorTypes...) -> overloaded<VisitorTypes...>;
184
185 template<typename... VisitorTypes>
187 make_overloads(VisitorTypes&&... visitors)
188 {
189 return { std::forward<VisitorTypes>(visitors)... };
190 }
191
192} // end of namespace tpf::types
193
194namespace types = tpf::types;
195
197{
198 using name_t = const char*;
199 using age_t = int;
200 using weight_t = double;
201 using inn_vt_t = std::variant<name_t, age_t>;
202
203 using variant_t = std::variant<age_t, weight_t, inn_vt_t>;
204
205 using container_t = std::vector<variant_t>;
206
207 container_t info;
208
209 info.emplace_back( inn_vt_t{"Thomas Kim"} );
210 info.emplace_back( 30 );
211 info.emplace_back( 60.5 );
212 info.emplace_back( inn_vt_t{"Sophie Turner"} );
213 info.emplace_back( 20 );
214 info.emplace_back( 56.7 );
215
217 auto endl = tpf::endl;
218
220 (
221 [&stream, &endl](auto&& age)
222 {
223 stream <<"Age is " << age << endl;
224 },
225
226 [&stream, &endl](auto&& weight)
227 {
228 stream << "Weight is " << weight << endl;
229 },
230
231 [&stream, &endl](auto&& vt)
232 {
234 (
235 [&stream, &endl](auto&& name)
236 {
237 stream << "Name is " << name << endl;
238 },
239
240 [&stream, &endl](auto&& age)
241 {
242 stream << "Age is " << age << endl;
243 }
244
245 )(std::forward<decltype(vt)>(vt));
246 }
247
248 ).for_each(info);
249
250 stream << endl;
251}
252
254{
255 using name_t = const char*;
256 using age_t = int;
257 using weight_t = double;
258 using variant_t = std::variant<name_t, age_t, weight_t>;
259
260 using container_t = std::set<variant_t>;
261
262 container_t info;
263
264 info.emplace("Thomas Kim");
265 info.emplace(30);
266 info.emplace(60.5);
267 info.emplace("Sophie Turner");
268 info.emplace(20);
269 info.emplace(56.7);
270
272 auto endl = tpf::endl;
273
275 (
276 [&stream, &endl](auto&& name)
277 {
278 stream <<"Name is " << name << endl;
279 },
280
281 [&stream, &endl](auto&& age)
282 {
283 stream <<"Age is " << age << endl;
284 },
285
286 [&stream, &endl](auto&& weight)
287 {
288 stream << "Weight is " << weight << endl;
289 }
290
291 ).for_each(info);
292
293 stream << endl;
294}
295
297{
298 using key_t = const char*;
299 using name_t = const char*;
300 using age_t = int;
301 using weight_t = double;
302 using variant_t = std::variant<name_t, age_t, weight_t>;
303
304 using container_t = std::map<key_t, variant_t>;
305
306 container_t info;
307
308 info["Programmer"] = "Thomas Kim";
309 info["Age"] = 30;
310 info["Weight"] = 60.5;
311 info["Actress"] = "Sophie Turner";
312 info["Her age"] = 20;
313 info["Her weight"] = 56.7;
314
316 auto endl = tpf::endl;
317
319 (
320 [&stream, &endl](auto&& key, auto&& name)
321 {
322 stream << key << " is " << name << endl;
323 },
324
325 [&stream, &endl](auto&& key, auto&& age)
326 {
327 stream << key << " is " << age << endl;
328 },
329
330 [&stream, &endl](auto&& key, auto&& weight)
331 {
332 stream << key << " is " << weight << endl;
333 }
334
335 ).for_each(info);
336
337 stream << endl;
338}
339
340int main()
341{
342 // stream <<"container vector " << endl;
344
345 // stream <<"\ncontainer set " << endl;
346 // test_visit_simplified_set();
347
348 // test_visit_simplified_map();
349}
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
void test_visit_simplified_set()
Definition: 31-visit.cpp:253
int main()
Definition: 31-visit.cpp:340
Type to string name conversions are defined.
Definition: 31-visit.cpp:7
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
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... >
overloaded< remove_cv_ref_t< VisitorTypes >... > make_overloads(VisitorTypes &&... visitors)
Definition: 31-visit.cpp:187
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:92
static enable_if_variant_t< VariantType > visit_variant(VisitorType &&visitor, VariantType &&vt)
Definition: 31-visit.cpp:70
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:156
std::tuple< VisitorTypes... > vistors_t
Definition: 31-visit.cpp:148
enable_if_variant_t< VariantType > operator()(VariantType &&vt) const
Definition: 31-visit.cpp:167
enable_if_pair_of_variant_t< PairType > operator()(PairType &&vt)
Definition: 31-visit.cpp:174
overloaded(VisitorTypes... visitors)
Definition: 31-visit.cpp:152
Stream output operators << are implemented.