C++ Library Extensions 2022.12.09
To help learn modern C++ programming
cpg_std_extensions.hpp
Go to the documentation of this file.
1/*
2 Author: Thomas Kim
3 First Edit: July 15, 2021
4*/
5
6#ifndef _CPG_STD_EXTENSIONS_HPP
7#define _CPG_STD_EXTENSIONS_HPP
8
9#ifndef NOMINMAX
10#define NOMINMAX
11#endif
12
13#include "cpg_types.hpp"
14#include "cpg_conversion.hpp"
15
16namespace std::inline stl_extensions
17{
18 namespace cgt = cpg::types;
19 using cgt::common_type_exists_c;
20
21 #if defined(CPG_INCLUDE_SYCL)
22
23 template<typename CharType, auto dims>
24 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
25 sycl::id<dims> const& ids)
26 {
27 if constexpr(dims == 1)
28 {
29 os << Cpg_CharStr("{: ")
30 << ids[0]
31 << Cpg_CharStr(" :}");
32 }
33 else if constexpr (dims == 2)
34 {
35 os << Cpg_CharStr("{: ")
36 << ids[0]
37 << Cpg_CharStr(", ")
38 << ids[1]
39 << Cpg_CharStr(" :}");
40 }
41 else if constexpr (dims == 3)
42 {
43 os << Cpg_CharStr("{: ")
44 << ids[0]
45 << Cpg_CharStr(", ")
46 << ids[1]
47 << Cpg_CharStr(", ")
48 << ids[2]
49 << Cpg_CharStr(" :}");
50 }
51 else
52 static_assert(dims <= 3);
53
54 return os;
55 }
56
57 template<typename CharType, auto dims>
58 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
59 sycl::range<dims> const& range)
60 {
61 if constexpr(dims == 1)
62 {
63 os << Cpg_CharStr("{: ")
64 << range[0]
65 << Cpg_CharStr(" :}");
66 }
67 else if constexpr (dims == 2)
68 {
69 os << Cpg_CharStr("{: ")
70 << range[0]
71 << Cpg_CharStr(", ")
72 << range[1]
73 << Cpg_CharStr(" :}");
74 }
75 else if constexpr (dims == 3)
76 {
77 os << Cpg_CharStr("{: ")
78 << range[0]
79 << Cpg_CharStr(", ")
80 << range[1]
81 << Cpg_CharStr(", ")
82 << range[2]
83 << Cpg_CharStr(" :}");
84 }
85 else
86 static_assert(dims <= 3);
87
88 return os;
89 }
90
91 #endif
92 // End of SYCL
93
95 template<template<typename, typename, typename...> class ContainerType,
96 typename EleType, typename Type, typename ...Types, std::common_with<EleType> S>
97 ContainerType<EleType, Type, Types...>&
98 operator << (ContainerType<EleType, Type, Types...>& container, S&& s)
99 requires requires { container.emplace_back(EleType{}); } ||
100 requires { container.emplace(container.end(), EleType{}); } ||
101 requires { container.emplace(EleType{}); }
102 {
103 Tpf_TestTrunction(EleType, s);
104
105 if constexpr(requires { container.emplace_back(EleType{}); } )
106 {
107 container.emplace_back(cgt::smart_forward<EleType, S>(s));
108 }
109 else if constexpr(requires { container.emplace(container.end(), EleType{}); } )
110 {
111 container.emplace(container.end(), cgt::smart_forward<EleType, S>(s));
112 }
113 else if constexpr(requires { container.emplace(EleType{}); } )
114 {
115 container.emplace(cgt::smart_forward<EleType, S>(s));
116 }
117
118 return container;
119 }
120
122 template<template<typename, typename, typename...> class ContainerType,
123 typename EleType, typename Type, typename ...Types, std::common_with<EleType> S>
124 ContainerType<EleType, Type, Types...>&
125 operator >> (ContainerType<EleType, Type, Types...>& container, S&& s) requires
126 requires { container.emplace_front(EleType{}); } ||
127 requires { container.emplace(container.begin(), EleType{}); } ||
128 requires { container.emplace(EleType{}); }
129 {
130 Tpf_TestTrunction(EleType, s);
131
132 if constexpr(requires { container.emplace_front(EleType{}); } )
133 {
134 container.emplace_front(cgt::smart_forward<EleType, S>(s));
135 }
136 else if constexpr(requires { container.emplace(container.begin(), EleType{}); } )
137 {
138 container.emplace(container.begin(), cgt::smart_forward<EleType, S>(s));
139 }
140 else if constexpr(requires { container.emplace(EleType{}); } )
141 {
142 container.emplace(cgt::smart_forward<EleType, S>(s));
143 }
144
145 return container;
146 }
147
148 template<typename Target, typename Source>
149 concept append_operator_c = requires(Target tgt, Source src)
150 {
151 { tgt << src } -> std::same_as<Target&>;
152 };
153
154 template<typename Target, typename Source>
155 concept prepend_operator_c = requires(Target tgt, Source src)
156 {
157 { tgt >> src } -> std::same_as<Target&>;
158 };
159
161 template<template<typename, typename, typename...> class ContainerType,
162 typename EleType, typename Type, typename ...Types,
163 cgt::view_flat_c ViewType>
164 ContainerType<EleType, Type, Types...>&
165 operator << (ContainerType<EleType, Type, Types...>& container, ViewType&& view) requires
166 requires { container.emplace_back(EleType{}); } ||
167 requires { container.insert(container.end(), EleType{}); } ||
168 requires { container.emplace(EleType{}); }
169 {
170 if constexpr(requires{ view.empty(); } )
171 {
172 if(view.empty()) return container;
173 }
174
175 if constexpr( requires { container.reserve(std::size_t{1}); view.size(); } )
176 {
177 container.reserve(container.size() + view.size());
178 }
179
180 for(auto s: view)
181 {
182 using S = decltype(s);
183
184 Tpf_TestTrunction(EleType, s);
185
186 if constexpr(requires { container.emplace_back(EleType{}); } )
187 {
188 container.emplace_back(cgt::smart_forward<EleType, S>(s));
189 }
190 else if constexpr(requires { container.insert(container.end(), EleType{}); } )
191 {
192 container.insert(container.end(), cgt::smart_forward<EleType, S>(s));
193 }
194 else if constexpr(requires { container.emplace(EleType{}); } )
195 {
196 container.emplace(cgt::smart_forward<EleType, S>(s));
197 }
198 }
199
200 return container;
201 }
202
204 template<template<typename, typename, typename...> class ContainerType,
205 typename EleType, typename Type, typename ...Types, cgt::view_flat_c ViewType>
206 ContainerType<EleType, Type, Types...>&
207 operator >> (ContainerType<EleType, Type, Types...>& container, ViewType&& view) requires
208 requires { container.emplace_front(EleType{}); } ||
209 requires { container.insert(container.begin(), EleType{}); } ||
210 requires { container.emplace(EleType{}); }
211 {
212 if constexpr(requires{ view.empty(); })
213 {
214 if(view.empty()) return container;
215 }
216
217 if constexpr( requires { container.reserve(std::size_t{1}); view.size(); })
218 {
219 container.reserve(container.size() + view.size());
220 }
221
222 for(auto s: view)
223 {
224 using S = decltype(s);
225
226 Tpf_TestTrunction(EleType, s);
227
228 if constexpr(requires { container.emplace_front(EleType{}); } )
229 {
230 container.emplace_front(cgt::smart_forward<EleType, S>(s));
231 }
232 else if constexpr(requires { container.insert(container.begin(), EleType{}); } )
233 {
234 container.insert(container.begin(), cgt::smart_forward<EleType, S>(s));
235 }
236 else if constexpr(requires { container.emplace(EleType{}); } )
237 {
238 container.emplace(cgt::smart_forward<EleType, S>(s));
239 }
240 }
241
242 return container;
243 }
244
245 template<typename CharType> std::basic_ostream<CharType>&
246 operator << (std::basic_ostream<CharType>& os, cpg::hidden::flush)
247 {
248 os << std::flush; return os;
249 }
250
251 template<typename CharType> std::basic_ostream<CharType>&
252 operator << (std::basic_ostream<CharType>& os, cpg::hidden::endl)
253 {
254 os << std::endl; return os;
255 }
256
257 template<typename CharType> std::basic_ostream<CharType>&
258 operator << (std::basic_ostream<CharType>& os, cpg::hidden::endL)
259 {
260 os << "\n" << std::endl; return os;
261 }
262
263 template<typename CharType> std::basic_ostringstream<CharType>&
264 operator << (std::basic_ostringstream<CharType>& os, cpg::hidden::clear)
265 {
266 if constexpr (std::same_as<CharType, char>)
267 {
268 os.str("");
269 }
270 else
271 {
272 os.str(L"");
273 }
274
275 os.clear(); return os;
276 }
277
278
279 template<typename CharType> std::basic_ostringstream<CharType>&
280 operator << (std::basic_ostringstream<CharType>& os, cpg::hidden::flush)
281 {
282 if constexpr(std::same_as<CharType, char>)
283 {
284 std::cout << os.str()
285 << std::flush;
286 os.str("");
287 }
288 else
289 {
290 auto msg = os.str();
293 os.str(L"");
294 }
295
296 os.clear(); return os;
297 }
298
299 template<typename CharType> std::basic_ostringstream<CharType>&
300 operator << (std::basic_ostringstream<CharType>& os, cpg::hidden::endl)
301 {
302 if constexpr(std::same_as<CharType, char>)
303 {
304 std::cout << os.str()
305 << std::endl;
306 os.str("");
307 }
308 else
309 {
310 auto msg = os.str();
313 os.str(L"");
314 }
315
316 os.clear(); return os;
317 }
318
319 template<typename CharType> std::basic_ostringstream<CharType>&
320 operator << (std::basic_ostringstream<CharType>& os, cpg::hidden::endL)
321 {
322 if constexpr(std::same_as<CharType, char>)
323 {
324 std::cout << os.str()
325 << "\n" << std::endl;
326 os.str("");
327 }
328 else
329 {
330 auto msg = os.str();
332 std::cout << "\n" << std::endl;
333 os.str(L"");
334 }
335
336 os.clear(); return os;
337 }
338
339 template<typename = void>
340 std::ostream& operator<<(std::ostream& os, const wchar_t* str)
341 {
342 namespace cvr = cpg::conversion;
344 return os;
345 }
346
347 template<typename = void>
348 std::ostream& operator<<(std::ostream& os, std::wstring const& str)
349 {
350 namespace cvr = cpg::conversion;
351 os << cvr::utf16_to_windows_codepage(str.c_str());
352 return os;
353 }
354
355 template<typename = void>
356 std::ostream& operator<<(std::ostream& os, const char8_t* str)
357 {
358 namespace cvr = cpg::conversion;
359 os << cvr::utf8_to_windows_codepage((const char*)str);
360 return os;
361 }
362
363 template<typename = void>
364 std::ostream& operator<<(std::ostream& os, std::u8string const& str)
365 {
366 namespace cvr = cpg::conversion;
367 os << cvr::utf8_to_windows_codepage((const char*)str.c_str());
368 return os;
369 }
370
371 template<typename = void>
372 std::wostream& operator<<(std::wostream& os, const char* str)
373 {
374 namespace cvr = cpg::conversion;
376 return os;
377 }
378
379 template<typename = void>
380 std::wostream& operator<<(std::wostream& os, const char8_t* str)
381 {
382 namespace cvr = cpg::conversion;
383 os << cvr::utf8_to_utf16((const char*)str);
384 return os;
385 }
386
387 template<typename = void>
388 std::wostream& operator<<(std::wostream& os, std::u8string const& str)
389 {
390 namespace cvr = cpg::conversion;
391 os << cvr::utf8_to_utf16((const char*)str.c_str());
392 return os;
393 }
394
395 template<typename CharType> std::basic_ostream<CharType>&
396 operator<<(std::basic_ostream<CharType>& os,
397 std::basic_stringstream<CharType> const& stream)
398 {
399 os << stream.str(); return os;
400 }
401
402 namespace hidden
403 {
404 template<typename... Ts, typename... Ss>
405 constexpr auto tuple_connect_tail(std::tuple<Ts...>, std::tuple<Ss...>)
406 {
407 return std::tuple<Ts..., Ss...>{};
408 }
409
410 template<typename T, typename... Ss>
411 constexpr auto tuple_pairs(T, std::tuple<Ss...>) // tuple_pairs
412 {
413 return std::tuple< std::tuple<T, Ss>... >{};
414 }
415
416 template<typename... Ts, typename... Ss>
417 constexpr auto tuple_pairs(std::tuple<Ts...>, std::tuple<Ss...>) // tuple_pairs
418 {
419 return std::tuple< std::tuple<Ts..., Ss>... >{};
420 }
421
422 template<typename... TT, typename T, typename... Ts, typename... Ss>
423 constexpr auto fn_tuple_cross_product(std::tuple<TT...> tt, std::tuple<T, Ts...> t, std::tuple<Ss...> s)
424 {
425 if constexpr(sizeof...(Ts) != 0)
426 return fn_tuple_cross_product( tuple_connect_tail(tt, tuple_pairs(T{}, s)), std::tuple<Ts...>{}, s);
427 else
428 return tuple_connect_tail(tt, tuple_pairs(T{}, s));
429 }
430 }
431 // end of namespace hidden
432
433 template<cgt::tuple_flat_c T, cgt::tuple_flat_c S, cgt::tuple_flat_c ... Tails>
434 constexpr auto tuple_cartesian_product_type(T A, S B, Tails... tails)
435 {
436 if constexpr(sizeof...(tails) > 0)
437 {
438 return tuple_cartesian_product_type(hidden::fn_tuple_cross_product(std::tuple{}, A, B), tails...);
439 }
440 else
441 {
442 return hidden::fn_tuple_cross_product(std::tuple{}, A, B);
443 }
444 }
445
446 namespace hidden
447 {
448 template<typename TupleA, typename... TupleTypes>
449 using tuple_cross_product_t = decltype((TupleA{} >> ... >> TupleTypes{}));
450 }
451 // end of namespace hidden
452
453 template<typename TupleA, typename... TupleTypes>
455 std::remove_cvref_t<TupleTypes>...>;
456
457 template<typename TupleA, typename... TupleTypes>
458 using tuple_cartesian_product_t = tuple_cross_product_t<TupleA, TupleTypes...>;
459
460 namespace hidden
461 {
462 template<typename L, typename R>
463 constexpr auto fn_common_signed_tuple(L const&, R const& )
464 {
466 }
467
468 template<typename... Ls, typename... Rs>
469 constexpr auto fn_common_signed_tuple(std::tuple<Ls...> L, std::tuple<Rs...> R)
470 {
471 return cgt::for_stallion<sizeof...(Ls)>([]<auto... i>(cgt::sequence<i...>)
472 {
473 return std::tuple{
474 fn_common_signed_tuple(std::tuple_element_t<i, std::tuple<Ls...>>{},
475 std::tuple_element_t<i, std::tuple<Rs...>>{})... };
476 });
477 }
478
479 template<typename TupleA, typename TupleB>
480 using common_signed_tuple_pair = decltype(fn_common_signed_tuple(TupleA{}, TupleB{}));
481
482 template<typename L, typename R>
483 constexpr auto fn_common_unsigned_tuple(L const&, R const& )
484 {
486 }
487
488 template<typename... Ls, typename... Rs>
489 constexpr auto fn_common_unsigned_tuple(std::tuple<Ls...> L, std::tuple<Rs...> R)
490 {
491 return cgt::for_stallion<sizeof...(Ls)>([]<auto... i>(cgt::sequence<i...>)
492 {
493 return std::tuple{
494 fn_common_unsigned_tuple(std::tuple_element_t<i, std::tuple<Ls...>>{},
495 std::tuple_element_t<i, std::tuple<Rs...>>{})... };
496 });
497 }
498
499 template<cgt::tuple_flat_c TupleA, cgt::tuple_flat_c TupleB>
500 using common_unsigned_tuple_pair = decltype(fn_common_unsigned_tuple(TupleA{}, TupleB{}));
501
502 template<cgt::tuple_flat_c TupleType>
503 constexpr auto fn_common_signed_tuples(TupleType Tuple)
504 {
505 return Tuple;
506 }
507
508 template<cgt::tuple_flat_c TupleA, cgt::tuple_flat_c TupleB, cgt::tuple_flat_c... TupleTypes>
509 constexpr auto fn_common_signed_tuples(TupleA A, TupleB B, TupleTypes... Tuples)
510 {
511 if constexpr(sizeof...(Tuples) == 0)
512 return fn_common_signed_tuple(A, B);
513 else
515 }
516
517 template<cgt::tuple_flat_c TupleType>
518 constexpr auto fn_common_unsigned_tuples(TupleType Tuple)
519 {
520 return Tuple;
521 }
522
523 template<cgt::tuple_flat_c TupleA, cgt::tuple_flat_c TupleB, cgt::tuple_flat_c... TupleTypes>
524 constexpr auto fn_common_unsigned_tuples(TupleA A, TupleB B, TupleTypes... Tuples)
525 {
526 if constexpr(sizeof...(Tuples) == 0)
528 else
530 }
531
532 // common signed tuple
533 template<cgt::tuple_flat_c TupleType, cgt::tuple_flat_c... TupleTypes>
534 using common_signed_tuple_t = decltype(hidden::fn_common_signed_tuples(TupleType{}, TupleTypes{}...));
535
536 // common unsigned tuple
537 template<cgt::tuple_flat_c TupleType, cgt::tuple_flat_c... TupleTypes>
538 using common_unsigned_tuple_t = decltype(hidden::fn_common_unsigned_tuples(TupleType{}, TupleTypes{}...));
539 }
540 // end of namespace hidden
541
542 // common signed tuple
543 template<cgt::tuple_flat_c TupleType, cgt::tuple_flat_c... TupleTypes>
546 std::remove_cvref_t<TupleTypes>...>;
547
548 // common unsigned tuple
549 template<cgt::tuple_flat_c TupleType, cgt::tuple_flat_c... TupleTypes>
551
552 template<typename CharType, typename Type>
553 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
554 const std::optional<Type>& opt);
555
556 template<typename CharType, typename FirstType, typename SecondType>
557 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
558 const std::pair<FirstType, SecondType>& pr)
559 {
560 os << Cpg_CharStr("< ") << pr.first
561 << Cpg_CharStr(", ") << pr.second
562 << Cpg_CharStr(" >"); return os;
563 }
564
565 template<typename CharType, typename... Types>
566 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
567 const std::tuple<Types...>& container);
568
569 template<typename CharType, typename Type, typename... Types>
570 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
571 const std::variant<Type, Types...>& v);
572
573 template<typename CharType, typename ContainerType>
574 requires (cgt::std_array_flat_c< ContainerType >
575 || cgt::span_flat_c< ContainerType >
576 || ( cgt::c_array_flat_c<ContainerType> && cgt::non_chars_c<ContainerType> ) )
577 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
578 ContainerType&& container);
579
580 template <class F, typename T, std::size_t N>
581 constexpr decltype(auto) apply(F&& f, T(&&c_array)[N]);
582
583 template <class F, typename T, std::size_t N>
584 constexpr decltype(auto) apply(F&& f, T(&c_array)[N]);
585
586 template< std::size_t I, class T, std::size_t N >
587 constexpr decltype(auto) get( T(&c_array)[N]) noexcept;
588
589 template< std::size_t I, class T, std::size_t N >
590 constexpr decltype(auto) get( T(&&c_array)[N]) noexcept;
591
592 template<typename CharType, typename T, T... Indices> std::basic_ostream<CharType>&
593 operator << (std::basic_ostream<CharType>& os,
594 std::integer_sequence<T, Indices...> const& seq) noexcept;
595
596 template<typename CharType, typename T> std::basic_ostream<CharType>&
597 operator >> (std::basic_ostream<CharType>& os, T const& t);
598
599 template<typename CharType, typename... Types> std::basic_ostream<CharType>&
600 operator >> (std::basic_ostream<CharType>& os, std::tuple<Types...> const& t);
601
602 namespace hidden
603 {
604 template<typename... Ls, typename... Rs>
605 constexpr decltype(auto) tuple_cartesian_product(std::tuple<Ls...> const& A, std::tuple<Rs...> const& B)
606 {
607 return cgt::for_stallion_tuple<sizeof...(Ls), sizeof...(Rs)>(
608 [&]<typename... seqs>( std::tuple<seqs...>)
609 {
610 auto append = [&]<auto ii, auto jj>(cgt::sequence<ii, jj>)
611 {
612 return cgt::tuple_append(std::get<ii>(A), std::get<jj>(B));
613 };
614
615 if constexpr(cgt::all_the_same_flat_c< decltype(append(seqs{}))...>)
616 return std::array{ append(seqs{})... };
617 else
618 return std::tuple{ append(seqs{})... };
619 });
620 }
621
622 template<typename... Ls, typename R, std::size_t N2>
623 constexpr decltype(auto) tuple_cartesian_product(std::tuple<Ls...> const& A, std::array<R, N2> const& B)
624 {
625 return cgt::for_stallion_tuple<sizeof...(Ls), N2>(
626 [&]<typename... seqs>( std::tuple<seqs...>)
627 {
628 auto append = [&]<auto ii, auto jj>(cgt::sequence<ii, jj>)
629 {
630 return cgt::tuple_append(std::get<ii>(A), std::get<jj>(B));
631 };
632
633 if constexpr(cgt::all_the_same_flat_c< decltype(append(seqs{}))... >)
634 return std::array{ append(seqs{})... };
635 else
636 return std::tuple{ append(seqs{})... };
637 });
638 }
639
640 template<typename L, std::size_t N1, typename... Rs>
641 constexpr decltype(auto) tuple_cartesian_product(std::array<L, N1> const& A, std::tuple<Rs...> const& B)
642 {
643 return cgt::for_stallion_tuple<N1, sizeof...(Rs)>(
644 [&]<typename... seqs>( std::tuple<seqs...>)
645 {
646 auto append = [&]<auto ii, auto jj>(cgt::sequence<ii, jj>)
647 {
648 return cgt::tuple_append(std::get<ii>(A), std::get<jj>(B));
649 };
650
651 if constexpr(cgt::all_the_same_flat_c< decltype(append(seqs{}))... >)
652 return std::array{ append(seqs{})... };
653 else
654 return std::tuple{ append(seqs{})... };
655 });
656 }
657
658 template<typename L, std::size_t N1, typename R, std::size_t N2>
659 constexpr decltype(auto) tuple_cartesian_product(std::array<L, N1> const& A, std::array<R, N2> const& B)
660 {
661 return cgt::for_stallion_tuple<N1, N2>(
662 [&]<typename... seqs>( std::tuple<seqs...>)
663 {
664 auto append = [&]<auto ii, auto jj>(cgt::sequence<ii, jj>)
665 {
666 return cgt::tuple_append(std::get<ii>(A), std::get<jj>(B));
667 };
668
669 if constexpr(cgt::all_the_same_flat_c< decltype(append(seqs{}))... >)
670 return std::array{ append(seqs{})... };
671 else
672 return std::tuple{ append(seqs{})... };
673 });
674 }
675 }
676 // end of namespace hidden
677
678 template<cgt::either_array_or_tuple_flat_c T, cgt::either_array_or_tuple_flat_c S,
679 cgt::either_array_or_tuple_flat_c... Tails>
680 constexpr decltype(auto) tuple_cartesian_product(T&& A, S&& B, Tails&&... tails)
681 {
682 if constexpr(sizeof...(Tails) > 0 )
683 {
685 }
686 else
687 {
689 }
690 }
691
692 template<typename CharType, typename T> std::basic_ostream<CharType>&
693 operator >> (std::basic_ostream<CharType>& os, T const& t)
694 {
695 using flat_t = std::remove_cvref_t<T>;
696
697 auto type_name = Cpg_GetTypeName(flat_t);
698
699 if constexpr(std::same_as<CharType, char>)
700 os << type_name;
701 else
703
704 return os;
705 }
706
707 template<typename CharType, typename... Types> std::basic_ostream<CharType>&
708 operator >> (std::basic_ostream<CharType>& os, std::tuple<Types...> const& t)
709 {
710 if constexpr(sizeof...(Types) != 0)
711 {
712 os << Cpg_CharStr("< ");
713
714 cgt::for_workhorse<decltype(t)>([&os](auto i)
715 {
716 using ele_t =
717 std::tuple_element_t<(std::size_t)i.value, std::tuple<Types...>>;
718
719 os >> ele_t{};
720
721 if(i.value != i.last) os << Cpg_CharStr(", ");
722 });
723
724 os << Cpg_CharStr("> "); return os;
725 }
726 else
727 {
728 os << Cpg_CharStr("< >"); return os;
729 }
730 }
731
732 namespace hidden
733 {
734 template<std::size_t SIZE, typename CharType>
735 void print_sequence(std::basic_ostream<CharType>& os, auto Index, auto count)
736 {
737 os << Index;
738 if( count != SIZE ) os << Cpg_CharStr(", ");
739 }
740 }
741 // end of namespace hidden
742
743 template<typename CharType, typename T, T... Indices> std::basic_ostream<CharType>&
744 operator << (std::basic_ostream<CharType>& os,
745 std::integer_sequence<T, Indices...> const& seq) noexcept
746 {
747 if constexpr(sizeof...(Indices) < 1 ) // count of Indices = 0
748 {
749 auto type_name = Cpg_GetTypeName(T);
750
751 os << Cpg_CharStr("< ");
752
753 if constexpr(std::same_as<CharType, char>)
754 os<< type_name;
755 else
757
758 os << Cpg_CharStr(" >");
759
760 return os;
761 }
762 else
763 {
764 constexpr auto SIZE = sizeof...(Indices);
765 std::size_t count = 0;
766
767 auto type_name = Cpg_GetTypeName(T);
768
769 os << Cpg_CharStr("< ");
770
771 if constexpr(std::same_as<CharType, char>)
772 os << type_name;
773 else
775
776 os << Cpg_CharStr(": ");
777
778 ( hidden::print_sequence<SIZE>(os, Indices, ++count) , ... );
779
780 os << Cpg_CharStr(" >"); return os;
781 }
782 }
783
784 /*
785 std::tuple_size(std::array) - https://en.cppreference.com/w/cpp/container/array/tuple_size
786 std::get(std::array) - https://en.cppreference.com/w/cpp/container/array/get
787 */
788
789 /* T: int, const int - auto
790 T&: int&, const int& - auto&
791 T&&: int&&, const int&& - auto&&
792 T&&, auto&&: rvalue reference, forwarding reference
793 function return type auto&& - rvalue reference
794 function parameter type auto&& - forwarding reference
795 decltype(auto) - function return type - auto, auto&, auto&&
796 */
797 template< std::size_t I, class T, std::size_t N >
798 constexpr decltype(auto) get( T(&c_array)[N]) noexcept
799 {
800 return c_array[I];
801 }
802
803 template< std::size_t I, class T, std::size_t N >
804 constexpr decltype(auto) get( T(&&c_array)[N]) noexcept
805 {
806 return std::move(c_array[I]);
807 }
808
809 // template <class F, typename T, std::size_t N>
810 // constexpr decltype(auto) apply(F&& f, T(&&c_array)[N])
811 // {
812 // using c_array_t = decltype(c_array);
813 // auto std_array = std::to_array( std::forward<c_array_t>(c_array) );
814
815 // return std::apply( std::forward<F>(f), std::move(std_array) );
816 // }
817
818 // template <class F, typename T, std::size_t N>
819 // constexpr decltype(auto) apply(F&& f, T(&c_array)[N])
820 // {
821 // auto std_array = std::to_array( c_array );
822
823 // return std::apply( std::forward<F>(f), std::move(std_array) );
824 // }
825
826 template <class F, typename T, std::size_t N>
827 constexpr decltype(auto) apply(F&& f, std::span<T, N>& sp)
828 {
829 cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
830 {
831 return std::apply( std::forward<F>(f), std::forward_as_tuple(sp[i]...));
832 });
833 }
834
835 template <class F, typename T, std::size_t N>
836 constexpr decltype(auto) apply(F&& f, const std::span<T, N>& sp)
837 {
838 cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
839 {
840 return std::apply( std::forward<F>(f), std::forward_as_tuple(sp[i]...));
841 });
842 }
843
844 template <class F, typename T, std::size_t N>
845 constexpr decltype(auto) apply(F&& f, std::span<T, N>&& sp)
846 {
847 cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
848 {
849 return std::apply( std::forward<F>(f), std::forward_as_tuple(sp[i]...));
850 });
851 }
852
853 /*
854 011 - C++ STL Container Class 판정법 - concept, requires, Type Requirements
855 https://www.youtube.com/watch?v=r4-kUPc7IJM&list=PLsIvhalfft1EtaiJJRmWKUGG0W1hyUKiw&index=11
856
857 */
858
859 template<typename CharType, typename Type>
860 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
861 const std::optional<Type>& opt)
862 {
863 if(opt)
864 {
865 os << opt.value();
866 }
867
868 return os;
869 }
870
871 template<typename CharType, cgt::stream_undefined_container_flat_c ContainerType>
872 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
873 ContainerType&& container)
874 {
875 if(container.empty())
876 {
877 os << Cpg_CharStr("{ }");
878 }
879 else
880 {
881 auto begin = container.begin();
882 auto last = container.end();
883
884 std::advance(last, -1); // --last; right before .end(), or iterator for the last element of the container
885
886 os << Cpg_CharStr("{ ");
887
888 for(auto itr = begin; itr != last; ++itr)
889 os << *itr << Cpg_CharStr(", ");
890
891 os << *last << Cpg_CharStr(" }");
892 }
893
894 return os;
895 }
896
898 template<typename CharType, cgt::view_flat_c ViewType> std::basic_ostream<CharType>&
899 operator<<(std::basic_ostream<CharType>& os, ViewType&& view)
900 {
901 if constexpr( requires{ view.empty(); } )
902 {
903 if(view.empty())
904 {
905 os << Cpg_CharStr("{: :}");
906 return os;
907 }
908 }
909
910 auto padding = Cpg_CharStr("{: ");
911
912 for(auto v: view)
913 {
914 os << padding << v;
915 padding = Cpg_CharStr(", ");
916 }
917
918 os << Cpg_CharStr(" :}");
919
920 return os;
921 }
922
923 template<typename CharType, cgt::map_c ContainerType>
924 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
925 const ContainerType& container)
926 {
927 if(container.empty())
928 {
929 os << Cpg_CharStr("{ }");
930 }
931 else
932 {
933 if constexpr(cgt::std_map_c<ContainerType>)
934 {
935 auto begin = container.begin();
936 auto last = container.end();
937
938 std::advance(last, -1);
939
940 os << Cpg_CharStr("{ ");
941
942 for(auto itr = begin; itr != last; ++itr)
943 {
944 os << *itr << Cpg_CharStr(", ");
945 }
946
947 os << *last << Cpg_CharStr(" }");
948 }
949 else if constexpr(cgt::tbb_map_c<ContainerType>)
950 {
951 auto begin = container.begin();
952 auto last = container.end();
953
954 std::advance(last, -1);
955
956 os << Cpg_CharStr("{ ");
957
958 for(auto itr = begin; itr != last; ++itr)
959 {
960 os << *itr;
961
962 auto ittr = itr;
963
964 if(++ittr != last) os << Cpg_CharStr(", ");
965 }
966
967 os << Cpg_CharStr(" }");
968 }
969 }
970
971 return os;
972 }
973
974 template<typename CharType, typename ContainerType>
975 requires (cgt::std_array_flat_c< ContainerType >
976 || cgt::span_flat_c< ContainerType >
977 || ( cgt::c_array_flat_c<ContainerType> && cgt::non_chars_c<ContainerType> ) )
978 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
979 ContainerType&& container)
980 {
981 auto begin = std::ranges::begin(container);
982 auto last = std::ranges::end(container);
983
984 if(begin == last) // container is empty()
985 {
986 os << Cpg_CharStr("< >");
987 }
988 else
989 {
990 --last; // right before .end(), or iterator for the last element of the container
991
992 os << Cpg_CharStr("< ");
993
994 for(auto itr = begin; itr != last; ++itr)
995 os << *itr << Cpg_CharStr(", ");
996
997 os << *last << Cpg_CharStr(" >");
998 }
999
1000 return os;
1001 }
1002
1003 namespace hidden
1004 {
1005 template<size_t Index, typename CharType, typename... Types>
1006 void print_tuple(std::basic_ostream<CharType>& os,
1007 const std::tuple<Types...>& container)
1008 {
1009 constexpr size_t Size = sizeof...(Types);
1010
1011 if constexpr ( Index < Size-1 ) // {0, 1, 2, ..., Index, Size - 1} < Size
1012 {
1013 os << std::get<Index>(container) << Cpg_CharStr(", ");
1014 print_tuple< Index + 1>(os, container);
1015 }
1016 else if constexpr(Index == Size - 1)
1017 {
1018 os << std::get<Index>(container);
1019 }
1020 }
1021 } // end of namespace hidden
1022
1023 template<typename CharType, typename... Types>
1024 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
1025 const std::tuple<Types...>& container)
1026 {
1027 if constexpr(sizeof...(Types) == 0)
1028 {
1029 os << Cpg_CharStr("[ ]");
1030 }
1031 else
1032 {
1033 os << Cpg_CharStr("[ ");
1034 hidden::print_tuple<0>(os, container);
1035 os << Cpg_CharStr(" ]");
1036 }
1037
1038 return os;
1039 }
1040
1041 template<typename CharType, typename Type, typename... Types>
1042 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
1043 const std::variant<Type, Types...>& v)
1044 {
1045 auto visit_target = [&os]<typename T>(T&& value) -> std::basic_ostream<CharType>&
1046 {
1047 if constexpr( cgt::ostream_operator_available_c< std::remove_cvref_t<T>, CharType>)
1048 os << value;
1049 else
1050 {
1051 if constexpr(std::same_as<CharType, char>)
1052 {
1053 os << Cpg_GetTypeCategory(value)
1054 <<" does not support ostream operator<<()" << std::endl;
1055 }
1056 else
1057 {
1058 auto type_name = Cpg_GetTypeCategory(value);
1059 os << cpg::types::hidden::ascii_conversion(type_name)
1060 << L" does not support ostream operator<<()" << std::endl;
1061 }
1062 }
1063
1064 return os;
1065 };
1066
1067 return std::visit(visit_target, v);
1068 }
1069
1070 #ifdef _TPF_TYPES_HPP
1071
1072 template<typename CharType, std::size_t N, typename T, typename deleter>
1073 std::basic_ostream<CharType>& operator << (std::basic_ostream<CharType>& os,
1075 {
1076 os << upw.ref(); return os;
1077 }
1078
1079 #endif
1080
1081} // end of std::inline stl_extensions
1082
1083
1084#endif // end of file _CPG_STD_EXTENSIONS_HPP
auto flush
Definition: 020-random.cpp:22
std::atomic< int > count
Definition: 022-mutex.cpp:10
auto & cout
auto & endl
tpf::sstream stream
std::string str() const
Definition: tpf_output.hpp:951
#define Cpg_CharStr(asciistr)
Definition: cpg_types.hpp:582
#define Cpg_GetTypeCategory(instance_arg,...)
Definition: cpg_types.hpp:743
#define Tpf_TestTrunction(TargetType, SourceValue)
Definition: cpg_types.hpp:1193
#define Cpg_GetTypeName(type_arg,...)
Definition: cpg_types.hpp:740
String conversions are implemented.
std::string utf16_to_windows_codepage(const std::wstring &utf16_string)
Converts UTF16 std::wstring to Windows codepage std::string.
std::wstring utf8_to_utf16(const std::string &utf8str)
Converts UTF8 std::string to UTF16 std::wstring.
std::wstring windows_codepage_to_utf16(const std::string &codepage_string)
Converts Windows codepage std::string to utf16 std::wstring.
std::string utf8_to_windows_codepage(const std::string &utf8_string)
Converts UTF8 std::string to Windows codepage string.
constexpr decltype(auto) for_stallion_tuple(WorkType &&work, std::tuple< Indices... > indices, ArgTypes &&... args)
Definition: cpg_types.hpp:4282
constexpr auto tuple_append(std::tuple< Ls... > const &A, sequence< Li... >, std::tuple< Rs... > const &B, sequence< Ri... >) noexcept
Definition: cpg_types.hpp:3937
constexpr decltype(auto) for_stallion(WorkType &&work, std::integer_sequence< T, Indices... >, ArgTypes &&... args)
Definition: cpg_types.hpp:3858
std::wstring ascii_conversion(std::string const &str)
Definition: cpg_types.hpp:262
make_signed_t< std::common_type_t< std::remove_cvref_t< Types >... > > common_signed_t
Definition: cpg_types.hpp:1012
make_unsigned_t< std::common_type_t< std::remove_cvref_t< Types >... > > common_unsigned_t
Definition: cpg_types.hpp:1016
std::integer_sequence< std::common_type_t< std::remove_cvref_t< decltype(Indices)>... >, Indices... > sequence
Definition: cpg_types.hpp:2665
constexpr auto tuple_connect_tail(std::tuple< Ts... >, std::tuple< Ss... >)
decltype(hidden::fn_common_unsigned_tuples(TupleType{}, TupleTypes{}...)) common_unsigned_tuple_t
decltype(fn_common_unsigned_tuple(TupleA{}, TupleB{})) common_unsigned_tuple_pair
constexpr auto tuple_pairs(std::tuple< Ts... >, std::tuple< Ss... >)
constexpr auto fn_common_unsigned_tuples(TupleA A, TupleB B, TupleTypes... Tuples)
constexpr auto fn_common_signed_tuple(std::tuple< Ls... > L, std::tuple< Rs... > R)
decltype(fn_common_signed_tuple(TupleA{}, TupleB{})) common_signed_tuple_pair
decltype((TupleA{} > > ... > > TupleTypes{})) tuple_cross_product_t
void print_tuple(std::basic_ostream< CharType > &os, const std::tuple< Types... > &container)
void print_sequence(std::basic_ostream< CharType > &os, auto Index, auto count)
decltype(hidden::fn_common_signed_tuples(TupleType{}, TupleTypes{}...)) common_signed_tuple_t
constexpr auto fn_common_unsigned_tuple(std::tuple< Ls... > L, std::tuple< Rs... > R)
constexpr auto fn_common_signed_tuples(TupleA A, TupleB B, TupleTypes... Tuples)
constexpr auto fn_tuple_cross_product(std::tuple< TT... > tt, std::tuple< T, Ts... > t, std::tuple< Ss... > s)
std::basic_ostream< CharType > & operator>>(std::basic_ostream< CharType > &os, std::tuple< Types... > const &t)
hidden::common_unsigned_tuple_t< TupleType, TupleTypes... > common_unsigned_tuple_t
hidden::common_signed_tuple_t< std::remove_cvref_t< TupleType >, std::remove_cvref_t< TupleTypes >... > common_signed_tuple_t
constexpr decltype(auto) tuple_cartesian_product(T &&A, S &&B, Tails &&... tails)
constexpr decltype(auto) get(T(&&c_array)[N]) noexcept
tuple_cross_product_t< TupleA, TupleTypes... > tuple_cartesian_product_t
constexpr decltype(auto) apply(F &&f, std::span< T, N > &&sp)
hidden::tuple_cross_product_t< std::remove_cvref_t< TupleA >, std::remove_cvref_t< TupleTypes >... > tuple_cross_product_t
constexpr auto tuple_cartesian_product_type(T A, S B, Tails... tails)
std::basic_ostream< CharType > & operator<<(std::basic_ostream< CharType > &os, const ContainerType &container)
std::pair< T, T > range
enable_if_variant_t< VariantType > visit(VisitorType &&visitor, VariantType &&vt)
Definition: 31-visit.cpp:118