C++ Library Extensions 2022.12.09
To help learn modern C++ programming
cpg_types.hpp
Go to the documentation of this file.
1/*
2 Author: Thomas Kim
3 First Edit: July 12, 2021
4 Second Edit: Dec. 07, 2021
5 Third Edit: Dec. 11, 2021 - safe binary operation - sbo()
6*/
7
8#ifndef _CPG_TYPES_HPP
9#define _CPG_TYPES_HPP
10
11#ifndef NOMINMAX
12#define NOMINMAX
13#endif
14
15#ifndef TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS
16#define TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS 1
17#endif
18
19#ifndef TBB_SUPPRESS_DEPRECATED_MESSAGES
20 #define TBB_SUPPRESS_DEPRECATED_MESSAGES 1
21#else
22 #undef TBB_SUPPRESS_DEPRECATED_MESSAGES
23 #define TBB_SUPPRESS_DEPRECATED_MESSAGES 1
24 #endif // end of TBB_SUPPRESS_DEPRECATED_MESSAGES
25
26#include <iostream>
27#include <memory>
28#include <ranges>
29#include <algorithm>
30#include <concepts>
31#include <type_traits>
32#include <variant>
33#include <vector>
34#include <set>
35#include <map>
36#include <array>
37#include <memory_resource>
38#include <deque>
39#include <unordered_set>
40#include <unordered_map>
41#include <tuple>
42#include <list>
43#include <string>
44#include <string_view>
45#include <cstring>
46#include <optional>
47#include <thread>
48#include <mutex>
49#include <execution>
50#include <sstream>
51#include <cstddef>
52#include <span>
53#include <numbers>
54#include <cassert>
55
56#if defined(CPG_INCLUDE_SYCL)
57 #include <cl/sycl.hpp>
58#endif
59
60#if defined(__cpp_lib_source_location)
61#include <source_location>
62#endif
63
64#include <tbb/tbb.h>
65
66#if defined(_DEBUG) || defined(DEBUG) || defined(CPG_DEBUG) || !defined(CPG_SAFE_OPERATION)
67#define CPG_SAFE_OPERATION 2LL
68#endif
69
70#if defined(CPG_SAFE_OPERATION) && ((CPG_SAFE_OPERATION<0) || (CPG_SAFE_OPERATION>2))
71#error Macro CPG_SAFE_OPERATION should be in the range [0, 2] inclusive
72#endif
73
74/*
75 if CPG_SAFE_OPERATION==0
76 perform type cast only
77
78 if CPG_SAFE_OPERATION==1LL
79 detect integral overflow and division by zero - (DEFAULT)
80
81 if _DEBUG || DEBUG || CPG_SAFE_OPERATION=2LL || CPG_SAFE_NUMERICAL_OPERATION==2LL
82 detect integral/floating-point overflow and division by zero
83*/
84
85#if defined(_DEBUG) || defined(DEBUG) || defined(CPG_DEBUG)
86 #define CpgSafe(arg) cpg::types::sbo<CPG_SAFE_OPERATION>(arg)
87#else
88 #define CpgSafe(arg) arg
89#endif
90
91namespace std
92{
93 /*
94 std::tuple_size(std::array) - https://en.cppreference.com/w/cpp/container/array/tuple_size
95 std::get(std::array) - https://en.cppreference.com/w/cpp/container/array/get
96
97 013 - if constexpr, type tag dispatch, integral_constant, bool_constant, true_type, false_type
98 https://www.youtube.com/watch?v=X_o99tZ1RkE&list=PLsIvhalfft1Fpu1DIMZ-4UVtPp7wnL0Hd&index=14
99
100 094 - C++ std::tuple 및 std::array 사용법 3 - std::to_array, std::apply
101 https://www.youtube.com/watch?v=LmWMTdk66gg&list=PLsIvhalfft1EtaiJJRmWKUGG0W1hyUKiw&index=93
102
103 */
104
105 template< class T, std::size_t N >
106 struct tuple_size< T[N] > :
107 std::integral_constant<std::size_t, N> { };
108
109 template< class T, std::size_t N >
110 struct tuple_size< const T[N] > :
111 std::integral_constant<std::size_t, N> { };
112
113 template< class T, std::size_t N >
114 struct tuple_size< T(&)[N] > :
115 std::integral_constant<std::size_t, N> { };
116
117 template< class T, std::size_t N >
118 struct tuple_size< const T(&)[N] > :
119 std::integral_constant<std::size_t, N> { };
120
121 template< class T, std::size_t N >
122 struct tuple_size< T(&&)[N] > :
123 std::integral_constant<std::size_t, N> { };
124
125 template< class T, std::size_t N >
126 struct tuple_size< const T(&&)[N] > :
127 std::integral_constant<std::size_t, N> { };
128
130
131 template< class ...Ts>
132 struct tuple_size<std::variant<Ts...>> :
133 std::integral_constant<std::size_t, sizeof...(Ts)> { };
134
135 template< class ...Ts>
136 struct tuple_size<const std::variant<Ts...>> :
137 std::integral_constant<std::size_t, sizeof...(Ts)> { };
138
139 template< class ...Ts>
140 struct tuple_size<std::variant<Ts...>&> :
141 std::integral_constant<std::size_t, sizeof...(Ts)> { };
142
143 template< class ...Ts>
144 struct tuple_size<const std::variant<Ts...>&> :
145 std::integral_constant<std::size_t, sizeof...(Ts)> { };
146
147 template< class ...Ts>
148 struct tuple_size<std::variant<Ts...>&&> :
149 std::integral_constant<std::size_t, sizeof...(Ts)> { };
150
151 template< class ...Ts>
152 struct tuple_size<const std::variant<Ts...>&&> :
153 std::integral_constant<std::size_t, sizeof...(Ts)> { };
154}
155// end of namespace std
156
158{
159 inline constexpr std::size_t operator""_size_t(unsigned long long value)
160 {
161 return static_cast<std::size_t>(value);
162 }
163
164 inline constexpr unsigned int operator""_unsigned(unsigned long long value)
165 {
166 return static_cast<unsigned int>(value);
167 }
168
169 inline constexpr short operator""_short(unsigned long long value)
170 {
171 return static_cast<short>(value);
172 }
173
174 inline constexpr unsigned short operator""_ushort(unsigned long long value)
175 {
176 return static_cast<unsigned short>(value);
177 }
178
179 inline constexpr char operator""_char(unsigned long long value)
180 {
181 return static_cast<char>(value);
182 }
183
184 inline constexpr char operator""_schar(unsigned long long value)
185 {
186 return static_cast<signed char>(value);
187 }
188
189 inline constexpr unsigned char operator""_uchar(unsigned long long value)
190 {
191 return static_cast<unsigned char>(value);
192 }
193
194 inline constexpr long double operator""_ldouble(long double value)
195 {
196 return value;
197 }
198}
199// end of namespace cpg::literals
200
201namespace cpg
202{
203 namespace hidden
204 {
205 struct flush{};
206 struct clear{};
207 struct endl{};
208 struct endL{};
209 }
210
211 inline constexpr auto flush = hidden::flush{};
212 inline constexpr auto clear = hidden::clear{};
213 inline constexpr auto endl = hidden::endl{};
214 inline constexpr auto endL = hidden::endL{};
215
216 template<typename Type>
217 inline constexpr auto type_max_v = std::numeric_limits<Type>::max();
218
219 inline constexpr size_t InvalidIndex = type_max_v<size_t>;
220 inline constexpr size_t SelectAll = InvalidIndex;
221
222 using big_integer_t = long long;
223 using big_unsigned_t = unsigned long long;
224
225 namespace types
226 {
227 template<typename Type>
228 inline constexpr auto not_a_number() noexcept
229 {
230 if constexpr(std::is_same_v<Type, float>)
231 return std::nanf("not a number");
232 else if constexpr(std::is_same_v<Type, double>)
233 return std::nan("not a number");
234 else if constexpr(std::is_same_v<Type, long double>)
235 return std::nanl("not a number");
236 else
237 return Type{};
238 }
239
240 template<std::size_t KeyIndex, typename Type, auto Index, auto... Indices>
241 constexpr auto get_nth_value(std::integer_sequence<Type, Index, Indices...>) noexcept
242 {
243 if constexpr(KeyIndex == 0)
244 return Index;
245 else if constexpr( KeyIndex != 0 && sizeof...(Indices) != 0)
246 {
247 return get_nth_value<KeyIndex-1>(std::integer_sequence<Type, Indices...>{});
248 }
249 else
250 return InvalidIndex;
251 }
252
253 struct cHarsTR
254 {
255 std::string m_char;
256 std::wstring m_wchar;
257 };
258
259 namespace hidden
260 {
261 template<typename = void>
262 std::wstring ascii_conversion(std::string const& str)
263 {
264 auto count = str.size();
265 std::wstring rlt(count, L'\0');
266
267 for(int i = 0; i < count; ++i)
268 (char&)rlt[i] = str[i];
269
270 return rlt;
271 }
272
273 template<typename = void>
274 std::string ascii_conversion(std::wstring const& str)
275 {
276 auto count = str.size();
277 std::string rlt(count, '\0');
278
279 for(int i = 0; i < count; ++i)
280 rlt[i] = (char)str[i];
281
282 return rlt;
283 }
284 }
285 // end of namespace hidden
286
287 template<typename CharType> std::basic_ostream<CharType>&
288 operator << (std::basic_ostream<CharType>& os, cpg::types::cHarsTR const& charstr)
289 {
290 if constexpr(std::same_as<CharType, char>)
291 os << charstr.m_char;
292 else
293 os << charstr.m_wchar;
294
295 return os;
296 }
297
298 template<typename OperationType, typename... DelimiterTypes> class fold_visitor;
299
300 template<typename OperationType, typename DelimiterType>
301 class fold_visitor<OperationType, DelimiterType>
302 {
303 protected:
304
305 long long m_arg_count;
306 long long m_left_count;
307 long long m_right_count;
308
309 OperationType m_operation;
310 DelimiterType m_delimiter;
311
312 public:
313
314 fold_visitor(auto arg_count, OperationType opr, DelimiterType del):
315 m_arg_count{(long long)arg_count}, m_left_count{0}, m_right_count{(long long)arg_count},
316 m_operation{ std::move(opr) }, m_delimiter{ std::move(del) }{ }
317
318 void reset() noexcept
319 {
320 this->m_left_count = 0;
321 this->m_right_count = this->m_arg_count;
322 }
323
324 void left_operation(auto&& arg)
325 {
326 this->m_operation(std::forward<decltype(arg)>(arg));
327
328 ++this->m_left_count;
329
330 if(m_left_count < m_arg_count)
331 {
332 if constexpr( requires { this->m_delimiter(std::forward<decltype(arg)>(arg)); } )
333 {
334 this->m_delimiter(std::forward<decltype(arg)>(arg));
335 }
336 else if constexpr(requires { this->m_delimiter(); })
337 {
338 this->m_delimiter();
339 }
340 }
341 }
342
343 void right_operation(auto&& arg)
344 {
345 if(m_right_count != m_arg_count)
346 {
347 if constexpr( requires { this->m_delimiter(std::forward<decltype(arg)>(arg)); } )
348 {
349 this->m_delimiter(std::forward<decltype(arg)>(arg));
350 }
351 else if constexpr(requires { this->m_delimiter(); })
352 {
353 this->m_delimiter();
354 }
355 }
356
357 --this->m_right_count;
358
359 this->m_operation(arg);
360 }
361
362 friend fold_visitor& operator << (fold_visitor& fv, auto&& arg)
363 {
364 fv.left_operation(std::forward<decltype(arg)>(arg));
365
366 return fv;
367 }
368
369 friend fold_visitor& operator >> (auto&& arg, fold_visitor& fv)
370 {
371 fv.right_operation(std::forward<decltype(arg)>(arg));
372
373 return fv;
374 }
375 };
376
377 template<typename OperationType, typename DelimiterOpen, typename DelimiterType, typename DelimiterClose>
378 class fold_visitor<OperationType, DelimiterOpen, DelimiterType, DelimiterClose>
379 {
380 protected:
381
382 long long m_arg_count;
383 long long m_left_count;
384 long long m_right_count;
385
386 OperationType m_operation;
387 DelimiterOpen m_open_delimiter;
388 DelimiterType m_delimiter;
389 DelimiterClose m_close_delimiter;
390
391 public:
392
393 fold_visitor(auto arg_count, OperationType opr,
394 DelimiterOpen d_open, DelimiterType del, DelimiterClose d_close):
395 m_arg_count{(long long)arg_count}, m_left_count{0}, m_right_count{(long long)arg_count},
396 m_operation{ std::move(opr) }, m_open_delimiter{ std::move(d_open) },
397 m_delimiter{ std::move(del) }, m_close_delimiter{ std::move(d_close) } { }
398
399 void reset() noexcept
400 {
401 this->m_left_count = 0;
402 this->m_right_count = this->m_arg_count;
403 }
404
405 void left_operation(auto&& arg)
406 {
407 if(this->m_left_count == 0)
408 {
409 if constexpr( requires { this->m_open_delimiter( std::forward<decltype(arg)>(arg) ); })
410 {
411 this->m_open_delimiter(std::forward<decltype(arg)>(arg));
412 }
413 else if constexpr(requires { this->m_open_delimiter(); })
414 {
415 this->m_open_delimiter();
416 }
417 }
418
419 this->m_operation(std::forward<decltype(arg)>(arg));
420
421 ++this->m_left_count;
422
423 if(m_left_count < m_arg_count)
424 {
425 if constexpr( requires { this->m_delimiter(std::forward<decltype(arg)>(arg)); } )
426 {
427 this->m_delimiter(std::forward<decltype(arg)>(arg));
428 }
429 else if constexpr(requires { this->m_delimiter(); })
430 {
431 this->m_delimiter();
432 }
433 }
434 else if(m_left_count == m_arg_count)
435 {
436 if constexpr( requires { this->m_close_delimiter( std::forward<decltype(arg)>(arg) ); })
437 {
438 this->m_close_delimiter(std::forward<decltype(arg)>(arg));
439 }
440 else if constexpr(requires { this->m_close_delimiter(); })
441 {
442 this->m_close_delimiter();
443 }
444 }
445 }
446
447 void right_operation(auto&& arg)
448 {
449 if(m_right_count == m_arg_count)
450 {
451 if constexpr( requires { this->m_open_delimiter( std::forward<decltype(arg)>(arg) ); })
452 {
453 this->m_open_delimiter(std::forward<decltype(arg)>(arg));
454 }
455 else if constexpr(requires { this->m_open_delimiter(); })
456 {
457 this->m_open_delimiter();
458 }
459 }
460 else if(m_right_count != m_arg_count)
461 {
462 if constexpr( requires { this->m_delimiter(std::forward<decltype(arg)>(arg)); } )
463 {
464 this->m_delimiter(std::forward<decltype(arg)>(arg));
465 }
466 else if constexpr(requires { this->m_delimiter(); })
467 {
468 this->m_delimiter();
469 }
470 }
471
472 --this->m_right_count;
473
474 this->m_operation(arg);
475
476 if(this->m_right_count == 0)
477 {
478 if constexpr( requires { this->m_close_delimiter( std::forward<decltype(arg)>(arg) ); })
479 {
480 this->m_close_delimiter(std::forward<decltype(arg)>(arg));
481 }
482 else if constexpr(requires { this->m_close_delimiter(); })
483 {
484 this->m_close_delimiter();
485 }
486 }
487 }
488
489 friend fold_visitor& operator << (fold_visitor& fv, auto&& arg)
490 {
491 fv.left_operation(std::forward<decltype(arg)>(arg));
492
493 return fv;
494 }
495
496 friend fold_visitor& operator >> (auto&& arg, fold_visitor& fv)
497 {
498 fv.right_operation(std::forward<decltype(arg)>(arg));
499
500 return fv;
501 }
502 };
503
504 template<typename OperationType>
505 class fold_visitor<OperationType>
506 {
507 OperationType m_operation;
508
509 public:
510
511 fold_visitor(OperationType opr): m_operation{ std::move(opr) } { }
512
513 void reset() noexcept { }
514
515 void call_operation(auto&& arg)
516 {
517 this->m_operation(std::forward<decltype(arg)>(arg));
518 }
519
520 friend fold_visitor& operator << (fold_visitor& fv, auto&& arg)
521 {
522 fv.call_operation(std::forward<decltype(arg)>(arg));
523 return fv;
524 }
525
526 friend fold_visitor& operator >> (auto&& arg, fold_visitor& fv)
527 {
528 fv.call_operation(std::forward<decltype(arg)>(arg));
529 return fv;
530 }
531 };
532
533 template<typename OperationType>
534 fold_visitor(OperationType)->fold_visitor<OperationType>;
535
536 template<typename OperationType, typename DelimiterType>
537 fold_visitor(auto, OperationType, DelimiterType)->fold_visitor<OperationType, DelimiterType>;
538
539 template<typename OperationType, typename DelimiterOpen, typename DelimiterType, typename DelimiterClose>
540 fold_visitor(auto arg_count, OperationType opr,
541 DelimiterOpen d_open, DelimiterType del, DelimiterClose d_close)
543
544 void print_args_inorder(auto&&... args)
545 {
546 int index = 0;
547
548 auto task = [&index](auto&& arg)
549 {
550 // we do our operation here
551 std::cout << index << ":" << arg;
552 ++index;
553 };
554
555 auto mid = []{ std::cout << ", "; };
556
557 fold_visitor visit{ sizeof...(args), task, mid };
558
559 ( visit << ... << args);
560 }
561
562 void print_args_reverse(auto&&... args)
563 {
564 int index = sizeof...(args) - 1;
565
566 auto task = [&index](auto&& arg)
567 {
568 // we do our operation here
569 std::cout << index << ":" << arg;
570 --index;
571 };
572
573 auto mid = []{ std::cout << ", "; };
574
575 fold_visitor visit{ sizeof...(args), task, mid };
576
577 ( visit << ... << args);
578 }
579 }
580}
581
582#define Cpg_CharStr(asciistr) cpg::types::cHarsTR{asciistr, L##asciistr}
583
584namespace cpg // C++ Programmers' Group
585{
586 class debug_exception: public std::exception
587 {
588 private:
589 std::string m_message;
590 int m_lineno;
591 std::string m_file_name;
592 std::string m_what_msg;
593
594 public:
595 debug_exception(std::string message, int lineno, std::string file_name):
596 m_lineno(lineno), m_message(message), m_file_name(file_name)
597 {
598 std::ostringstream os;
599
600 os << "debug_exception - file [" << this->m_file_name << "]\n";
601 os << "thread id [" << std::this_thread::get_id() << "] - ";
602 os << "line [" << this->m_lineno<<"]\n";
603 os << "message: " << this->m_message;
604
605 this->m_what_msg = os.str();
606 }
607
608 virtual const char* what() const noexcept override
609 {
610 return this->m_what_msg.c_str();
611 }
612
613 }; // end of class debug_exception
614
615 namespace types
616 {
617 template<typename Type>
618 std::string type_tO_sTring()
619 {
620 #ifdef __NVCC__
621 {
622 std::string fname = typeid(hidden::st_dummy_type_container<Type>).name();
623
624 const char* to_str = "struct tpf::types::hidden::st_dummy_type_container<";
625
626 std::size_t len = strlen(to_str);
627
628 auto pos = fname.find(to_str);
629
630 if(pos != fname.npos) // we found substring
631 fname = fname.substr(pos + len);
632
633 // remove trailing "> "
634 fname.pop_back();
635
637
638 to_str = " __ptr64"; len = strlen(to_str);
639 while( (pos = fname.find(to_str)) != fname.npos)
640 fname.erase(pos, len);
641
642 to_str = " __ptr32"; len = strlen(to_str);
643 while( (pos = fname.find(to_str)) != fname.npos)
644 fname.erase(pos, len);
645
646 to_str = "enum class"; len = strlen(to_str);
647 while( (pos = fname.find(to_str)) != fname.npos)
648 fname.erase(pos, len);
649
650 to_str = "enum"; len = strlen(to_str);
651 while( (pos = fname.find(to_str)) != fname.npos)
652 fname.erase(pos, len);
653
654 to_str = "class"; len = strlen(to_str);
655 while( (pos = fname.find(to_str)) != fname.npos)
656 fname.erase(pos, len);
657
658 to_str = "struct"; len = strlen(to_str);
659 while( (pos = fname.find(to_str)) != fname.npos)
660 fname.erase(pos, len);
661
662 while(fname.back() == ' ') fname.pop_back();
663
664 return fname;
665 }
666
667 #elif defined(__FUNCSIG__)
668 std::string fname(__FUNCSIG__);
669 const char* to_str = "tO_sTring<";
670 size_t len = strlen(to_str);
671 auto pos = fname.find("tO_sTring<");
672 fname = fname.substr(pos+len);
673 fname = fname.substr(0, fname.find_last_of('>'));
674
676
677 to_str = " __ptr64"; len = strlen(to_str);
678 while( (pos = fname.find(to_str)) != fname.npos)
679 fname.erase(pos, len);
680
681 to_str = " __ptr32"; len = strlen(to_str);
682 while( (pos = fname.find(to_str)) != fname.npos)
683 fname.erase(pos, len);
684
685 to_str = "enum class"; len = strlen(to_str);
686 while( (pos = fname.find(to_str)) != fname.npos)
687 fname.erase(pos, len);
688
689 to_str = "enum"; len = strlen(to_str);
690 while( (pos = fname.find(to_str)) != fname.npos)
691 fname.erase(pos, len);
692
693 to_str = "class"; len = strlen(to_str);
694 while( (pos = fname.find(to_str)) != fname.npos)
695 fname.erase(pos, len);
696
697 to_str = "struct"; len = strlen(to_str);
698 while( (pos = fname.find(to_str)) != fname.npos)
699 fname.erase(pos, len);
700
701 while(fname.back() == ' ') fname.pop_back();
702
703 return fname;
704 #else
705
706 std::string fname(__PRETTY_FUNCTION__);
707
708 #ifdef __clang_major__
709 const char* ftext = "[Type = ";
710 auto pos = fname.find(ftext) + strlen(ftext);
711 fname = fname.substr(pos);
712 fname.pop_back();
713 return fname;
714
715 #elif defined(__ICL)
716 const char* ftext = "type_tO_sTring<";
717 auto pos = fname.find(ftext) + strlen(ftext);
718 fname = fname.substr(pos);
719 pos = fname.find_last_of('>');
720 return fname.substr(0, pos);
721 #else
722 const char* ftext = "[with Type = ";
723 auto pos = fname.find(ftext) + strlen(ftext);
724 fname = fname.substr(pos);
725 pos = fname.find_first_of(';');
726 return fname.substr(0, pos);
727 #endif
728 #endif
729
730 } // end of type_tO_sTring()
731 }
732}
733
734/*
735 With best respect to Hyunho Cho:
736
737 #define get_type_name(T, ...) type_name<T, ##__VA_ARGS__>()
738 #define get_type_category(V, ...) type_name<decltype(V, ##__VA_ARGS__)>()
739*/
740#define Cpg_GetTypeName(type_arg, ...) \
741 cpg::types::type_tO_sTring<type_arg, ##__VA_ARGS__>()
742
743#define Cpg_GetTypeCategory(instance_arg, ...) \
744 cpg::types::type_tO_sTring<decltype(instance_arg, ##__VA_ARGS__)>()
745
746#define Cpg_DebugException(debug_message) cpg::debug_exception{debug_message, __LINE__, __FILE__}
747
748#define Cpg_ThrowDebugException(debug_message) throw cpg::debug_exception{debug_message, __LINE__, __FILE__}
749
750namespace cpg
751{
752
753#if defined(CPG_SAFE_OPERATION) && (CPG_SAFE_OPERATION > 0)
754 constexpr const bool bDetectOverFlow = true;
755#else
756 constexpr const bool bDetectOverFlow = false;
757#endif
758
759 namespace types
760 {
761 template<auto... args>
763
764 namespace hidden
765 {
766 template<typename Type>
768
769 template<auto... args>
771 }
772
773 template<typename Type>
774 concept nontype_container_c = hidden::st_nontype_container< std::remove_cvref_t<Type> >::value;
775
776 template<typename CharType>
777 void display_nontypes( std::basic_ostream<CharType>& os, nontype_container<> ) noexcept
778 { }
779
780 template<typename CharType, auto arg, auto... args>
781 void display_nontypes( std::basic_ostream<CharType>& os, nontype_container<arg, args...> ) noexcept
782 {
783 std::cout << arg; // we consumed arg
784
785 if constexpr( sizeof...(args) != 0)
786 {
787 std::cout << Cpg_CharStr(", ") ;
788
790 }
791 }
792
793 template<typename CharType, auto... args>
794 std::basic_ostream<CharType>& operator <<
795 (std::basic_ostream<CharType>& os, nontype_container<args...> ) noexcept
796 {
797 os << Cpg_CharStr("(: ");
798
799 display_nontypes(os, nontype_container<args...>{} );
800 os << Cpg_CharStr(" :)");
801
802 return os;
803 }
804
805 template<typename CharType, auto... args>
806 std::basic_ostream<CharType>& operator >>
807 (std::basic_ostream<CharType>& os, nontype_container<args...> nc) noexcept
808 {
809 os << nc; return os;
810 }
811
812 template<std::size_t Index, auto arg, auto... args>
813 constexpr auto get( nontype_container<arg, args...>) noexcept
814 {
815 if constexpr( Index == 0) // we consume arg
816 return arg;
817 else if constexpr( Index > 0 && sizeof...(args) != 0)
818 {
819 return get<Index - 1>( nontype_container<args...>{} );
820 }
821 else
822 return InvalidIndex; // (std::size_t)-1
823 }
824
825 struct no_type{ };
826
827 template<typename... Types> struct type_container{ };
828
830 namespace hidden
831 {
832 template<std::size_t N, typename FuncType, typename Type, typename... Types>
833 constexpr auto fn_return_type(FuncType func, type_container<Type, Types...> )
834 {
835 if constexpr( requires{ func( Type{}, Types{} ... ); } )
836 return func( Type{}, Types{} ... );
837 else if constexpr( sizeof...(Types) + 1 < N )
838 return fn_return_type<N>(func, type_container<Type, Type, Types...>{} );
839 else
840 return no_type{};
841 }
842
843 template<std::size_t N, typename FuncType, typename Type, typename... Types>
844 constexpr auto argument_count(FuncType func, type_container<Type, Types...> )
845 {
846 if constexpr( requires{ func( Type{}, Types{} ... ); } )
847 return sizeof...(Types) + 1 ;
848 else if constexpr( sizeof...(Types) + 1 < N )
849 return argument_count<N>(func, type_container<Type, Type, Types...>{} );
850 else
851 return cpg::InvalidIndex;
852 }
853
854 }
855 // end of namespace hidden
856
857 template<typename FuncType, typename Type>
858 constexpr auto return_type(FuncType func, Type)
859 {
860 return hidden::fn_return_type<31>(func, type_container<Type>{});
861 }
862
863 template<typename FuncType, typename Type>
864 using return_type_t = decltype(return_type( std::declval<FuncType>(), Type{}));
865
866 template<typename FuncType, typename Type>
867 constexpr auto argument_count(FuncType func, Type)
868 {
869 return hidden::argument_count<20>(func, type_container<Type>{});
870 }
871
872 template<typename T>
873 concept numerical_c = std::integral<std::remove_cvref_t<T>> ||
874 std::floating_point<std::remove_cvref_t<T>>;
875
876 template<typename T>
877 concept arithmetic_c = std::is_arithmetic_v<std::remove_cvref_t<T>>;
878
879 template<typename Type>
880 struct range
881 {
882 Type begin;
883
884 union
885 {
886 Type span; Type end;
887 };
888 };
889
890 template<typename CharType, typename Type> std::basic_ostream<CharType>&
891 operator<<(std::basic_ostream<CharType>& os, range<Type> const& r)
892 {
893 os << Cpg_CharStr("< ")
894 << r.begin<< Cpg_CharStr(", ")
895 << r.end << Cpg_CharStr(" >");
896
897 return os;
898 }
899
900 template<typename Type>
901 range(Type)->range<Type>;
902
903 template<typename Type>
904 range(Type, Type)->range<Type>;
905
906 template<auto Id, auto... Ids>
907 using index_t = std::index_sequence<(std::size_t)Id, (std::size_t)Ids...>;
908
909 template<auto N>
910 using make_index_t = std::make_index_sequence<(std::size_t)N>;
911
912 template<typename ...Types>
913 using index_for = std::make_index_sequence<sizeof...(Types)>;
914
915 template<typename T, T Value>
917 {
918 using type = T;
919 static constexpr T Index = Value;
920 static constexpr T Size = Value;
921 };
922
923 template<auto Index>
924 using indexer_t = indexer_type< std::remove_cvref_t<decltype(Index)>, Index>;
925
926 template<typename P>
927 concept pointer_c = std::is_pointer_v<std::remove_cvref_t<P>>;
928
929 template<typename FuncType, typename PointerType>
931 requires (PointerType p, FuncType func) { func(p); };
932
933 template<pointer_c PointerType, pointer_callable_c<PointerType> FuncType>
934 auto raii_create_object(PointerType object_ptr, FuncType func)
935 {
936 auto deleter = [func](auto ptr)
937 {
938 if(ptr) func(ptr);
939 };
940
941 return std::unique_ptr< std::remove_pointer_t<PointerType>, decltype(deleter)>
942 { object_ptr, deleter };
943 }
944
945 template<typename CharType>
946 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
947 no_type const& oh_no)
948 {
949 os << "no_type or void"; return os;
950 }
951
952 template<typename T>
953 concept no_type_c = std::same_as<std::remove_cvref_t<T>, no_type>;
954
955 template<typename T>
956 concept valid_type_c = !(std::is_void_v<T> || no_type_c<T>);
957
958 template<typename T>
959 concept resize_available_c = requires (T o) { o.resize( std::size_t{1}); };
960
961 template<typename ContainerType>
962 concept push_back_available_c = requires (ContainerType container)
963 {
964 typename ContainerType::value_type;
965
966 container.push_back(typename ContainerType::value_type{});
967 };
968
969 namespace hidden
970 {
971 template<typename T>
973
974 template<std::integral T>
976 {
977 using type = std::make_signed_t<T>;
978 };
979
980 template<std::floating_point T>
981 struct st_signed_type<T>
982 {
983 using type = T;
984 };
985
987 template<typename T>
989
990 template<std::integral T>
992 {
993 using type = std::make_unsigned_t<T>;
994 };
995
996 template<std::floating_point T>
997 struct st_unsigned_type<T>
998 {
999 using type = T;
1000 };
1001 }
1002 // end of namespace hidden
1003
1004 template<typename T>
1006
1007 template<typename T>
1009
1010 template<typename... Types>
1013
1014 template<typename... Types>
1017
1018 inline constexpr auto difference_absolute(arithmetic_c auto a, arithmetic_c auto b) noexcept
1019 {
1020 using a_t = decltype(a);
1021 using b_t = decltype(b);
1022
1023 if constexpr( std::is_floating_point_v<a_t> || std::is_floating_point_v<b_t> ||
1024 (std::is_unsigned_v<a_t> && std::is_unsigned_v<b_t>) )
1025 {
1026 return a > b ? (a - b) : (b - a);
1027 }
1028 else
1029 {
1031
1032 signed_t aa = a, bb = b;
1033 return aa > bb ? (aa - bb) : (bb - aa);
1034 }
1035 }
1036
1037 template<typename... Types>
1038 concept common_type_exists_c = requires
1039 {
1040 // std::common_type<Types...> 내에
1041 // type 멤버가 존재하는가? 를 묻습니다.
1042 // Type requirement
1043 typename std::common_type<Types...>::type;
1044 };
1045
1046 template<typename P, typename T>
1047 concept same_flat_c = std::same_as< std::remove_cvref_t<P>, std::remove_cvref_t<T> >;
1048
1049 template<typename P, typename... Types>
1050 concept all_same_c = ( std::same_as<P, Types> && ... );
1051
1052 template<std::floating_point T, std::integral S> // (s, s)
1053 constexpr decltype(auto) numeric_cast(S s)
1054 {
1055 std::optional<T> result;
1056
1057 if(std::numeric_limits<T>::min() <= s &&
1058 s <= std::numeric_limits<T>::max())
1059 {
1060 #if defined(_DEBUG) || defined(DEBUG) || defined(CPG_DEBUG)
1061 if(static_cast<T>(s) == s)
1062 result = static_cast<T>(s);
1063 #else
1064 result = static_cast<T>(s);
1065 #endif
1066 }
1067
1068 return result;
1069 }
1070
1071 template<std::integral T, std::floating_point S> // (s, s)
1072 constexpr decltype(auto) numeric_cast(S s)
1073 {
1074 std::optional<T> result;
1075
1076 if(std::numeric_limits<T>::min() <= s &&
1077 s <= std::numeric_limits<T>::max())
1078 {
1079 #if defined(_DEBUG) || defined(DEBUG) || defined(CPG_DEBUG)
1080 if(static_cast<T>(s) == s)
1081 result = static_cast<T>(s);
1082 #else
1083 result = static_cast<T>(s);
1084 #endif
1085 }
1086
1087 return result;
1088 }
1089
1090 template<std::signed_integral T, std::signed_integral S> // (s, s)
1091 constexpr decltype(auto) numeric_cast(S s)
1092 {
1093 if(std::numeric_limits<T>::min() <= s &&
1094 s <= std::numeric_limits<T>::max())
1095 return std::optional<T>{ static_cast<T>(s) };
1096 else
1097 return std::optional<T>{ };
1098 }
1099
1100 template<std::signed_integral T, std::unsigned_integral U> // (s, u)
1101 constexpr decltype(auto) numeric_cast(U u)
1102 {
1103 if( u <= std::numeric_limits<T>::max())
1104 return std::optional<T>{ static_cast<T>(u) };
1105 else
1106 return std::optional<T>{ };
1107 }
1108
1109 template<std::unsigned_integral T, std::signed_integral S> // (u, s)
1110 constexpr decltype(auto) numeric_cast(S s)
1111 {
1112 if(s >= 0 && s <= std::numeric_limits<T>::max())
1113 return std::optional<T>{ static_cast<T>(s) };
1114 else
1115 return std::optional<T>{ };
1116 }
1117
1118 template<std::unsigned_integral T, std::unsigned_integral U> // (u, u)
1119 constexpr decltype(auto) numeric_cast(U u)
1120 {
1121 if(u <= std::numeric_limits<T>::max())
1122 return std::optional<T>{ static_cast<T>(u) };
1123 else
1124 return std::optional<T>{ };
1125 }
1126
1127 template<std::floating_point T, numerical_c S>
1128 constexpr decltype(auto) numeric_cast(S s)
1129 {
1130 if(std::numeric_limits<T>::min() <= s &&
1131 s <= std::numeric_limits<T>::max())
1132 return std::optional<T>{ static_cast<T>(s) };
1133 else
1134 return std::optional<T>{ };
1135 }
1136
1137 #if defined(__cpp_lib_source_location)
1138
1139 void log_location(const std::string_view message,
1140 const std::source_location location =
1141 std::source_location::current())
1142 {
1143 std::cout << "file: "
1144 << location.file_name() << "("
1145 << location.line() << ":"
1146 << location.column() << ") \""
1147 << location.function_name() << "\": "
1148 << message;
1149 }
1150
1151 template<typename EleType, typename S>
1152 void truncation_test(S&& s,
1153 const std::source_location location = std::source_location::current())
1154 {
1155 if constexpr(numerical_c<EleType> && numerical_c<S>)
1156 {
1157 auto result = numeric_cast<EleType>(s);
1158
1159 if(!result)
1160 {
1161 std::ostringstream msg;
1162 msg << "truncated from " << s
1163 <<" to " << static_cast<EleType>(s) << std::endl;
1164
1165 log_location(msg.str(), location);
1166 }
1167 }
1168 }
1169 #else
1170 template<typename EleType, typename S>
1172 {
1173 if constexpr(numerical_c<EleType> && numerical_c<S>)
1174 {
1175 auto result = numeric_cast<EleType>(s);
1176
1177 if(!result)
1178 {
1179 std::cout<< "WARNING: truncated from " << s
1180 <<" to " << static_cast<EleType>(s) << std::endl;
1181 }
1182 }
1183 }
1184 #endif
1185 }
1186 // end of namespace types
1187}
1188// end of namespace cpg::types
1189
1190#if defined(_DEBUG) || defined(DEBUG) || defined(CPG_DEBUG)
1191 #define Tpf_TestTrunction(TargetType, SourceValue) cpg::types::truncation_test<TargetType>(SourceValue)
1192#else
1193 #define Tpf_TestTrunction(TargetType, SourceValue)
1194#endif
1195
1196namespace cpg
1197{
1198 namespace types
1199 {
1200 template<numerical_c... ArgTypes>
1201 constexpr decltype(auto) signed_cast(ArgTypes... args)
1202 {
1203 using c_t = common_signed_t<ArgTypes...>;
1204
1205 return std::tuple{ numeric_cast<c_t>(args)... };
1206 }
1207
1208 template<numerical_c... ArgTypes>
1209 constexpr decltype(auto) unsigned_cast(ArgTypes... args)
1210 {
1211 using c_t = common_unsigned_t<ArgTypes...>;
1212
1213 return std::tuple{ numeric_cast<c_t>(args)...};
1214 }
1215
1216 template<typename T>
1217 constexpr auto check_operation_validity(T&& target)
1218 {
1219 if constexpr(std::floating_point<std::remove_cvref_t<T>>)
1220 {
1221 if(target != target) // test if not a number or nan
1222 return false;
1223 else if(target == target + 1) // positive or negative infinity
1224 return false;
1225 else
1226 return true;
1227 }
1228 else
1229 return true;
1230 }
1231
1233
1234 template <class TargetType, class _Ty>
1235 [[nodiscard]] constexpr std::enable_if_t<std::is_same_v<std::remove_reference_t<TargetType>,
1236 std::remove_reference_t<_Ty>>, _Ty&&>
1237 smart_forward(std::remove_reference_t<_Ty>& _Arg) noexcept
1238 {
1239 // std::cout <<"forwarding" << std::endl;
1240 return static_cast<_Ty&&>(_Arg);
1241 }
1242
1243 template <class TargetType, class _Ty>
1244 [[nodiscard]] constexpr std::enable_if_t< !std::is_same_v<std::remove_reference_t<TargetType>,
1245 std::remove_reference_t<_Ty>> && std::common_with<TargetType, _Ty>, TargetType>
1246 smart_forward(std::remove_reference_t<_Ty>& _Arg) noexcept
1247 {
1248 // std::cout <<"casting"<< std::endl;
1249 return static_cast<TargetType>(_Arg);
1250 }
1251
1252 template <class TargetType, class _Ty>
1253 [[nodiscard]] constexpr std::enable_if_t< std::is_same_v<std::remove_reference_t<TargetType>,
1254 std::remove_reference_t<_Ty>>, _Ty&&>
1255 smart_forward(std::remove_reference_t<_Ty>&& _Arg) noexcept
1256 {
1257 // std::cout <<"forwarding" << std::endl;
1258 static_assert(!std::is_lvalue_reference_v<_Ty>, "bad forward call");
1259 return static_cast<_Ty&&>(_Arg);
1260 }
1261
1262 template <class TargetType, class _Ty>
1263 [[nodiscard]] constexpr std::enable_if_t< !std::is_same_v<std::remove_reference_t<TargetType>,
1264 std::remove_reference_t<_Ty>>&& std::common_with<TargetType, _Ty>, TargetType>
1265 smart_forward(std::remove_reference_t<_Ty>&& _Arg) noexcept
1266 {
1267 // std::cout <<"casting"<< std::endl;
1268 return static_cast<TargetType>(_Arg);
1269 }
1270
1271 template <class TargetType, class _Ty>
1272 [[nodiscard]] constexpr std::enable_if_t< std::is_same_v<std::remove_reference_t<TargetType>,
1273 std::remove_reference_t<_Ty>>, std::remove_reference_t<_Ty>&&>
1274 smart_move(_Ty&& _Arg) noexcept
1275 {
1276 // forward _Arg as movable
1277 return static_cast<std::remove_reference_t<_Ty>&&>(_Arg);
1278 }
1279
1280 template <class TargetType, class _Ty>
1281 [[nodiscard]] constexpr std::enable_if_t< !std::is_same_v<std::remove_reference_t<TargetType>,
1282 std::remove_reference_t<_Ty>>, TargetType>
1283 smart_move(_Ty&& _Arg) noexcept
1284 {
1285 // forward _Arg as movable
1286 return static_cast<TargetType>(_Arg);
1287 }
1288
1289 template<auto N, typename T, typename Deleter>
1290 inline auto& cast_ref(std::unique_ptr<T[], Deleter>& uptr) noexcept
1291 {
1292 return reinterpret_cast<T(&)[N]>(uptr[0]);
1293 }
1294
1295 template<auto N, typename T, typename Deleter>
1296 inline auto& cast_ref(std::index_sequence<N>, std::unique_ptr<T[], Deleter>& uptr) noexcept
1297 {
1298 return reinterpret_cast<T(&)[N]>(uptr[0]);
1299 }
1300
1301 template<auto N, typename T, typename Deleter>
1302 inline auto& cast_ref(std::unique_ptr<T[], Deleter> const& uptr) noexcept
1303 {
1304 return reinterpret_cast<const T(&)[N]>(uptr[0]);
1305 }
1306
1307 template<auto N, typename T, typename Deleter>
1308 inline auto& cast_ref(std::index_sequence<N>, std::unique_ptr<T[], Deleter> const& uptr) noexcept
1309 {
1310 return reinterpret_cast<const T(&)[N]>(uptr[0]);
1311 }
1312
1313 template<auto N1, auto N2, typename T, typename Deleter>
1314 inline auto& cast_ref(std::unique_ptr<T[], Deleter>& uptr) noexcept
1315 {
1316 return reinterpret_cast<T(&)[N1][N2]>(uptr[0]);
1317 }
1318
1319 template<auto N1, auto N2, typename T, typename Deleter>
1320 inline auto& cast_ref(std::index_sequence<N1, N2>, std::unique_ptr<T[], Deleter>& uptr) noexcept
1321 {
1322 return reinterpret_cast<T(&)[N1][N2]>(uptr[0]);
1323 }
1324
1325 template<auto N1, auto N2, typename T, typename Deleter>
1326 inline auto& cast_ref(std::unique_ptr<T[], Deleter> const& uptr) noexcept
1327 {
1328 return reinterpret_cast<const T(&)[N1][N2]>(uptr[0]);
1329 }
1330
1331 template<auto N1, auto N2, typename T, typename Deleter>
1332 inline auto& cast_ref(std::index_sequence<N1, N2>, std::unique_ptr<T[], Deleter> const& uptr) noexcept
1333 {
1334 return reinterpret_cast<const T(&)[N1][N2]>(uptr[0]);
1335 }
1337 template<auto N1, auto N2, auto N3, typename T, typename Deleter>
1338 inline auto& cast_ref(std::unique_ptr<T[], Deleter>& uptr) noexcept
1339 {
1340 return reinterpret_cast<T(&)[N1][N2][N3]>(uptr[0]);
1341 }
1342
1343 template<auto N1, auto N2, auto N3, typename T, typename Deleter>
1344 inline auto& cast_ref(std::index_sequence<N1, N2, N3>, std::unique_ptr<T[], Deleter>& uptr) noexcept
1345 {
1346 return reinterpret_cast<T(&)[N1][N2][N3]>(uptr[0]);
1347 }
1348
1349 template<auto N1, auto N2, auto N3, typename T, typename Deleter>
1350 inline auto& cast_ref(std::unique_ptr<T[], Deleter> const& uptr) noexcept
1351 {
1352 return reinterpret_cast<const T(&)[N1][N2][N3]>(uptr[0]);
1353 }
1354
1355 template<auto N1, auto N2, auto N3, typename T, typename Deleter>
1356 inline auto& cast_ref(std::index_sequence<N1, N2, N3>, std::unique_ptr<T[], Deleter> const& uptr) noexcept
1357 {
1358 return reinterpret_cast<const T(&)[N1][N2][N3]>(uptr[0]);
1359 }
1360
1361 template<auto N1, auto N2, typename T, auto N,
1362 typename = std::enable_if_t<N1* N2 == N>>
1363 inline auto& cast_ref(T(&array)[N]) noexcept
1364 {
1365 using array2_t = T[N1][N2];
1366 return reinterpret_cast<array2_t&>(array[0]);
1367 }
1368
1369 template<auto N1, auto N2, typename T, auto N,
1370 typename = std::enable_if_t<N1* N2 == N>>
1371 inline auto& cast_ref(std::index_sequence<N1, N2>, T(&array)[N]) noexcept
1372 {
1373 using array2_t = T[N1][N2];
1374 return reinterpret_cast<array2_t&>(array[0]);
1375 }
1376
1377 template<auto N1, auto N2, typename T, auto N = N1 * N2>
1378 inline auto& cast_ref(T(&array)[N1][N2]) noexcept
1379 {
1380 using array_t = T[N];
1381 return reinterpret_cast<array_t&>(array[0][0]);
1382 }
1383
1384 template<auto N1, auto N2, typename T, auto N = N1 * N2>
1385 inline auto& cast_ref(std::index_sequence<N1, N2>, T(&array)[N1][N2]) noexcept
1386 {
1387 using array_t = T[N];
1388 return reinterpret_cast<array_t&>(array[0][0]);
1389 }
1390
1391 template<auto N1, auto N2, auto N3, typename T, auto N,
1392 typename = std::enable_if_t<N1* N2* N3 == N>>
1393 inline auto& cast_ref(T(&array)[N]) noexcept
1394 {
1395 using array3_t = T[N1][N2][N3];
1396 return reinterpret_cast<array3_t&>(array[0]);
1397 }
1398
1399 template<auto N1, auto N2, auto N3, typename T, auto N,
1400 typename = std::enable_if_t<N1* N2* N3 == N>>
1401 inline auto& cast_ref(std::index_sequence<N1, N2, N3>, T(&array)[N]) noexcept
1402 {
1403 using array3_t = T[N1][N2][N3];
1404 return reinterpret_cast<array3_t&>(array[0]);
1405 }
1406
1407 template<auto N1, auto N2, auto N3, typename T, auto N = N1 * N2* N3>
1408 inline auto& cast_ref(T(&array)[N1][N2][N3]) noexcept
1409 {
1410 using array_t = T[N];
1411 return reinterpret_cast<array_t&>(array[0][0][0]);
1412 }
1413
1414 template<auto N1, auto N2, auto N3, typename T, auto N = N1 * N2* N3>
1415 inline auto& cast_ref(std::index_sequence<N1, N2, N3>, T(&array)[N1][N2][N3]) noexcept
1416 {
1417 using array_t = T[N];
1418 return reinterpret_cast<array_t&>(array[0][0][0]);
1419 }
1420
1421 template<auto N, typename T,
1422 typename = std::enable_if_t<std::is_pointer_v<T>>>
1423 inline auto& cast_ref(T array) noexcept
1424 {
1425 using ele_t = std::remove_pointer_t<T>;
1426
1427 using array_t = ele_t[N];
1428 return reinterpret_cast<array_t&>(array[0]);
1429 }
1430
1431 template<auto N1, auto N2, typename T,
1432 typename = std::enable_if_t<std::is_pointer_v<T>>>
1433 inline auto& cast_ref(T array) noexcept
1434 {
1435 using ele_t = std::remove_pointer_t<T>;
1436
1437 using array_t = ele_t[N1][N2];
1438 return reinterpret_cast<array_t&>(array[0]);
1439 }
1440
1441 template<auto N1, auto N2, auto N3, typename T,
1442 typename = std::enable_if_t<std::is_pointer_v<T>>>
1443 inline auto& cast_ref(T array) noexcept
1444 {
1445 using ele_t = std::remove_pointer_t<T>;
1446
1447 using array_t = ele_t[N1][N2][N3];
1448 return reinterpret_cast<array_t&>(array[0]);
1449 }
1450
1451 template<auto N, typename T,
1452 typename = std::enable_if_t<std::is_pointer_v<T>>>
1453 inline auto& cast_ref(std::index_sequence<N>, T array) noexcept
1454 {
1455 using ele_t = std::remove_pointer_t<T>;
1456 using array_t = ele_t[N];
1457 return reinterpret_cast<array_t&>(array[0]);
1458 }
1459
1460 template<auto N1, auto N2, typename T,
1461 typename = std::enable_if_t<std::is_pointer_v<T>>>
1462 inline auto& cast_ref(std::index_sequence<N1, N2>, T array) noexcept
1463 {
1464 using ele_t = std::remove_pointer_t<T>;
1465 using array_t = ele_t[N1][N2];
1466 return reinterpret_cast<array_t&>(array[0]);
1467 }
1468
1469 template<auto N1, auto N2, auto N3, typename T,
1470 typename = std::enable_if_t<std::is_pointer_v<T>>>
1471 inline auto& cast_ref(std::index_sequence<N1, N2, N3>, T array) noexcept
1472 {
1473 using ele_t = std::remove_pointer_t<T>;
1474
1475 using array_t = ele_t[N1][N2][N3];
1476 return reinterpret_cast<array_t&>(array[0]);
1477 }
1478
1479 template<std::size_t N1, typename T, std::size_t N,
1480 typename = std::enable_if_t<N1 == N>>
1481 inline auto& cast_ref(std::array<T, N>& array) noexcept
1482 {
1483 using c_array_t = T[N];
1484 return reinterpret_cast<c_array_t&>(array[0]);
1485 }
1486
1487 template<std::size_t N1, typename T, std::size_t N,
1488 typename = std::enable_if_t<N1 == N>>
1489 inline auto& cast_ref(std::array<T, N> const& array) noexcept
1490 {
1491 using c_array_t = const T[N];
1492 return reinterpret_cast<c_array_t&>(array[0]);
1493 }
1494
1495 template<std::size_t N1, std::size_t N2, typename T, std::size_t N,
1496 typename = std::enable_if_t< N1 * N2 == N>>
1497 inline auto& cast_ref(std::array<T, N>& array) noexcept
1498 {
1499 using c_array_t = T[N1][N2];
1500 return reinterpret_cast<c_array_t&>(array[0]);
1501 }
1502
1503 template<std::size_t N1, std::size_t N2, typename T, std::size_t N,
1504 typename = std::enable_if_t< N1 * N2 == N>>
1505 inline auto& cast_ref(std::array<T, N> const& array) noexcept
1506 {
1507 using c_array_t = const T[N1][N2];
1508 return reinterpret_cast<c_array_t&>(array[0]);
1509 }
1510
1511 template<std::size_t N1, typename T, std::size_t N,
1512 typename = std::enable_if_t< N1 == N>>
1513 inline auto& cast_ref(std::index_sequence<N1>, std::array<T, N>& array) noexcept
1514 {
1515 using c_array_t = T[N1];
1516 return reinterpret_cast<c_array_t&>(array[0]);
1517 }
1518
1519 template<std::size_t N1, typename T, std::size_t N,
1520 typename = std::enable_if_t< N1 == N>>
1521 inline auto& cast_ref(std::index_sequence<N1>, std::array<T, N> const& array) noexcept
1522 {
1523 using c_array_t = const T[N1];
1524 return reinterpret_cast<c_array_t&>(array[0]);
1525 }
1526
1527 template<std::size_t N1, std::size_t N2, typename T, std::size_t N,
1528 typename = std::enable_if_t< N1 * N2 == N>>
1529 inline auto& cast_ref(std::index_sequence<N1, N2>, std::array<T, N>& array) noexcept
1530 {
1531 using c_array_t = T[N1][N2];
1532 return reinterpret_cast<c_array_t&>(array[0]);
1533 }
1534
1535 template<std::size_t N1, std::size_t N2, typename T, std::size_t N,
1536 typename = std::enable_if_t< N1 * N2 == N>>
1537 inline auto& cast_ref(std::index_sequence<N1, N2>, std::array<T, N> const& array) noexcept
1538 {
1539 using c_array_t = const T[N1][N2];
1540 return reinterpret_cast<c_array_t&>(array[0]);
1541 }
1542
1543 template<std::size_t N1, std::size_t N2, std::size_t N3, typename T, std::size_t N,
1544 typename = std::enable_if_t< N1 * N2 * N3 == N>>
1545 inline auto& cast_ref(std::array<T, N>& array) noexcept
1546 {
1547 using c_array_t = T[N1][N2][N3];
1548 return reinterpret_cast<c_array_t&>(array[0]);
1549 }
1550
1551 template<std::size_t N1, std::size_t N2, std::size_t N3, typename T, std::size_t N,
1552 typename = std::enable_if_t< N1 * N2 * N3 == N>>
1553 inline auto& cast_ref(std::array<T, N> const& array) noexcept
1554 {
1555 using c_array_t = const T[N1][N2][N3];
1556 return reinterpret_cast<c_array_t&>(array[0]);
1557 }
1558
1559 template<std::size_t N1, std::size_t N2, std::size_t N3, typename T, std::size_t N,
1560 typename = std::enable_if_t< N1 * N2 * N3 == N>>
1561 inline auto& cast_ref(std::index_sequence<N1, N2, N3>, std::array<T, N>& array) noexcept
1562 {
1563 using c_array_t = T[N1][N2][N3];
1564 return reinterpret_cast<c_array_t&>(array[0]);
1565 }
1566
1567 template<std::size_t N1, std::size_t N2, std::size_t N3, typename T, std::size_t N,
1568 typename = std::enable_if_t< N1 * N2 * N3 == N>>
1569 inline auto& cast_ref(std::index_sequence<N1, N2, N3>, std::array<T, N> const& array) noexcept
1570 {
1571 using c_array_t = const T[N1][N2][N3];
1572 return reinterpret_cast<c_array_t&>(array[0]);
1573 }
1574
1575 template<std::size_t N, typename T>
1576 inline auto& cast_ref(std::vector<T>& vctr) noexcept
1577 {
1578 assert(N == vctr.size());
1579
1580 using c_array_t = T[N];
1581 return reinterpret_cast<c_array_t&>(vctr[0]);
1582 }
1583
1584 template<std::size_t N, typename T>
1585 inline auto& cast_ref(std::vector<T> const& vctr) noexcept
1586 {
1587 assert(N == vctr.size());
1588
1589 using c_array_t = const T[N];
1590 return reinterpret_cast<c_array_t&>(vctr[0]);
1591 }
1592
1593 template<std::size_t N, typename T>
1594 inline auto& cast_ref(std::index_sequence<N>, std::vector<T>& vctr) noexcept
1595 {
1596 assert(N == vctr.size());
1597
1598 using c_array_t = T[N];
1599 return reinterpret_cast<c_array_t&>(vctr[0]);
1600 }
1601
1602 template<std::size_t N, typename T>
1603 inline auto& cast_ref(std::index_sequence<N>, std::vector<T> const& vctr) noexcept
1604 {
1605 assert(N == vctr.size());
1606
1607 using c_array_t = const T[N];
1608 return reinterpret_cast<c_array_t&>(vctr[0]);
1609 }
1610
1611 template<std::size_t N1, std::size_t N2, typename T>
1612 inline auto& cast_ref(std::vector<T>& vctr) noexcept
1613 {
1614 assert(N1 * N2 == vctr.size());
1615
1616 using c_array_t = T[N1][N2];
1617 return reinterpret_cast<c_array_t&>(vctr[0]);
1618 }
1619
1620 template<std::size_t N1, std::size_t N2, typename T>
1621 inline auto& cast_ref(std::vector<T> const& vctr) noexcept
1622 {
1623 assert(N1 * N2 == vctr.size());
1624
1625 using c_array_t = const T[N1][N2];
1626 return reinterpret_cast<c_array_t&>(vctr[0]);
1627 }
1628
1629 template<std::size_t N1, std::size_t N2, typename T>
1630 inline auto& cast_ref(std::index_sequence<N1, N2>, std::vector<T>& vctr) noexcept
1631 {
1632 assert(N1 * N2 == vctr.size());
1633
1634 using c_array_t = T[N1][N2];
1635 return reinterpret_cast<c_array_t&>(vctr[0]);
1636 }
1637
1638 template<std::size_t N1, std::size_t N2, typename T>
1639 inline auto& cast_ref(std::index_sequence<N1, N2>, std::vector<T> const& vctr) noexcept
1640 {
1641 assert(N1 * N2 == vctr.size());
1642
1643 using c_array_t = const T[N1][N2];
1644 return reinterpret_cast<c_array_t&>(vctr[0]);
1645 }
1646
1647 template<std::size_t N1, std::size_t N2, std::size_t N3, typename T>
1648 inline auto& cast_ref(std::vector<T>& vctr) noexcept
1649 {
1650 assert(N1 * N2 * N3 == vctr.size());
1651
1652 using c_array_t = T[N1][N2][N3];
1653 return reinterpret_cast<c_array_t&>(vctr[0]);
1654 }
1655
1656 template<std::size_t N1, std::size_t N2, std::size_t N3, typename T>
1657 inline auto& cast_ref(std::vector<T> const& vctr) noexcept
1658 {
1659 assert(N1 * N2 * N3 == vctr.size());
1660
1661 using c_array_t = const T[N1][N2][N3];
1662 return reinterpret_cast<c_array_t&>(vctr[0]);
1663 }
1664
1665 template<std::size_t N1, std::size_t N2, std::size_t N3, typename T>
1666 inline auto& cast_ref(std::index_sequence<N1, N2, N3>, std::vector<T>& vctr) noexcept
1667 {
1668 assert(N1 * N2 * N3 == vctr.size());
1669
1670 using c_array_t = T[N1][N2][N3];
1671 return reinterpret_cast<c_array_t&>(vctr[0]);
1672 }
1673
1674 template<std::size_t N1, std::size_t N2, std::size_t N3, typename T>
1675 inline auto& cast_ref(std::index_sequence<N1, N2, N3>, std::vector<T> const& vctr) noexcept
1676 {
1677 assert(N1 * N2 * N3 == vctr.size());
1678
1679 using c_array_t = const T[N1][N2][N3];
1680 return reinterpret_cast<c_array_t&>(vctr[0]);
1681 }
1682
1683 template<size_t N1, size_t N2, typename T, size_t N,
1684 typename = std::enable_if_t<N1* N2 == N>>
1685 inline auto cast_array(T(&array)[N]) noexcept
1686 {
1687 using array_t = T[N1][N2];
1688 return *reinterpret_cast<array_t*>(array);
1689 }
1690
1691 template<size_t N1, size_t N2, typename T, size_t N = N1 * N2>
1692 inline auto cast_array(T(&array)[N1][N2]) noexcept
1693 {
1694 using array_t = T[N];
1695 return *reinterpret_cast<array_t*>(array);
1696 }
1697
1698 template<size_t N1, size_t N2, size_t N3, typename T, size_t N,
1699 typename = std::enable_if_t<N1* N2* N3 == N>>
1700 inline auto cast_array(T(&array)[N]) noexcept
1701 {
1702 using array_t = T[N1][N2][N3];
1703 return *reinterpret_cast<array_t*>(array);
1704 }
1705
1706 template<size_t N1, size_t N2, size_t N3, typename T, size_t N = N1 * N2* N3>
1707 inline auto cast_array(T(&array)[N1][N2][N3]) noexcept
1708 {
1709 using array_t = T[N];
1710 return *reinterpret_cast<array_t*>(array);
1711 }
1712
1713 template<typename T, size_t N>
1714 inline auto cast_array(std::array<T, N>& array) noexcept
1715 {
1716 using c_array_t = T[N];
1717 return *reinterpret_cast<c_array_t*>(array.data());
1718 }
1719
1720 template<typename T, size_t N>
1721 inline auto cast_array(std::array<T, N> const& array) noexcept
1722 {
1723 using c_array_t = const T[N];
1724 return *reinterpret_cast<c_array_t*>(array.data());
1725 }
1726
1727 template<size_t N1, size_t N2, typename T, size_t N,
1728 typename = std::enable_if_t< N1 * N2 == N>>
1729 inline auto cast_array(std::array<T, N>& array) noexcept
1730 {
1731 using c_array_t = T[N1][N2];
1732 return *reinterpret_cast<c_array_t*>(array.data());
1733 }
1734
1735 template<size_t N1, size_t N2, typename T, size_t N,
1736 typename = std::enable_if_t< N1 * N2 == N>>
1737 inline auto cast_array(std::array<T, N> const& array) noexcept
1738 {
1739 using c_array_t = const T[N1][N2];
1740 return *reinterpret_cast<c_array_t*>(array.data());
1741 }
1742
1743 template<size_t N1, size_t N2, size_t N3, typename T, size_t N,
1744 typename = std::enable_if_t< N1 * N2 * N3 == N>>
1745 inline auto cast_array(std::array<T, N>& array) noexcept
1746 {
1747 using c_array_t = T[N1][N2][N3];
1748 return *reinterpret_cast<c_array_t*>(array.data());
1749 }
1750
1751 template<size_t N1, size_t N2, size_t N3, typename T, size_t N,
1752 typename = std::enable_if_t< N1 * N2 * N3 == N>>
1753 inline auto cast_array(std::array<T, N> const& array) noexcept
1754 {
1755 using c_array_t = T[N1][N2][N3];
1756 return *reinterpret_cast<c_array_t*>(array.data());
1757 }
1758
1760
1761 namespace hidden
1762 {
1763 template<typename S, typename T>
1765 {
1766 using type = no_type;
1767 };
1768
1769 template< template<typename, typename...> class ContainerTmpl,
1770 typename S, typename... S_tail, typename T, typename... T_tail>
1771 requires ( common_type_exists_c<S, T> && !std::is_same_v<ContainerTmpl<S, S_tail...>, std::tuple<S, S_tail...> > )
1772 struct st_common_container< ContainerTmpl<S, S_tail...>, ContainerTmpl<T, T_tail...>>
1773 {
1774 using common_t = std::common_type_t<S, T>;
1775
1776 using type = std::conditional_t< std::is_same_v<S, common_t>,
1777 ContainerTmpl<S, S_tail...>, ContainerTmpl<T, T_tail...>>;
1778 };
1779
1780 template< template<typename, std::size_t> class ContainerTmpl,
1781 typename S, typename T, std::size_t M, std::size_t N>
1782 requires ( common_type_exists_c<S, T> )
1783 struct st_common_container< ContainerTmpl<S, M>, ContainerTmpl<T, N>>
1784 {
1785 using common_t = std::common_type_t<S, T>;
1786 using type = ContainerTmpl<common_t, M + N>;
1787 };
1788
1789 template< template<typename, std::size_t> class ContainerTmpl,
1790 typename S, typename T, std::size_t N>
1791 requires ( common_type_exists_c<S, T> )
1792 struct st_common_container< ContainerTmpl<S, N>, ContainerTmpl<T, N>>
1793 {
1794 using common_t = std::common_type_t<S, T>;
1795 using type = ContainerTmpl<common_t, N>;
1796 };
1797
1798 template< typename... Ss, typename... Ts>
1799 requires ( sizeof...(Ss) == sizeof...(Ts) && ( common_type_exists_c<Ss, Ts> && ... ) )
1800 struct st_common_container< std::tuple<Ss...>, std::tuple<Ts...>>
1801 {
1802 using type = std::tuple< std::common_type_t<Ss, Ts>... >;
1803 };
1804 }
1805 // end of namespace hidden
1806
1807 template<typename S, typename T>
1809
1810
1811 namespace hidden
1812 {
1813 template<typename FuncType, typename... ArgTypes>
1814 auto safe_apply(FuncType&& f, std::tuple<ArgTypes...> const& args)
1815 -> decltype( f( std::declval<ArgTypes>()...));
1816
1817 template<typename FuncType, typename ArgType, std::size_t N, std::size_t... Ints>
1818 auto array_apply(FuncType&& f, std::array<ArgType, N> const& args,
1819 std::index_sequence<Ints...>)-> decltype( f( std::get<Ints>(args)... ));
1820
1821 no_type array_apply(...); // fall-back function, catch-all function
1822
1823 template<typename FuncType, typename ArgType, std::size_t N>
1824 auto safe_apply(FuncType&& f, std::array<ArgType, N> const& args)
1825 -> decltype( array_apply(f, args, std::make_index_sequence<N>{}) );
1826
1827 no_type safe_apply(...); // fall-back function, catch-all function
1828
1829 template<typename FuncType, typename TupleType>
1830 auto fn_apply(FuncType&& f, TupleType&& args) -> decltype( safe_apply(f, args) );
1831 no_type fn_apply(...); // fall-back function, catch-all function
1832 }
1833
1834 template<typename FuncType, typename TupleType>
1835 using apply_return_t = decltype(hidden::fn_apply(std::declval<FuncType>(), std::declval<TupleType>()));
1836
1837 template<typename FuncType, typename... TupleTypes>
1838 using common_apply_t = std::common_type_t< apply_return_t<FuncType, TupleTypes>... >;
1839
1840 template<typename FuncType, typename TupleType>
1842
1843 template<typename FuncType, typename... TupleTypes>
1844 constexpr bool all_apply_v = ( is_apply_v<FuncType, TupleTypes> && ... );
1845
1846 template<typename FuncType, typename... TupleTypes>
1847 constexpr bool common_apply_v = all_apply_v<FuncType, TupleTypes...> &&
1849
1850 template<typename ReturnType, typename FuncType, typename... TupleTypes>
1852 std::enable_if_t< all_apply_v<FuncType, TupleTypes...>, ReturnType>;
1853
1854 template<typename FuncType, typename... TupleTypes>
1855 using apply_return_tuple_t = std::tuple< apply_return_t<FuncType, TupleTypes> ...>;
1856
1857 template<typename FuncType, typename... TupleTypes>
1859 std::array<std::common_type_t<apply_return_t<FuncType, TupleTypes>...>, sizeof...(TupleTypes)>;
1860
1861 template<typename FuncType, typename... TupleTypes>
1863 std::vector<std::common_type_t<apply_return_t<FuncType, TupleTypes>...>>;
1864
1865 template<typename FuncType, typename... TupleTypes>
1866 using void_if_all_apply_t = enable_if_all_apply_t<void, FuncType, TupleTypes...>;
1867
1868 template<typename FuncType, typename... TupleTypes>
1870 enable_if_all_apply_t< apply_return_tuple_t<FuncType, TupleTypes...>, FuncType, TupleTypes...>;
1871
1872 template<typename FuncType, typename... TupleTypes>
1874 enable_if_all_apply_t< apply_return_array_t<FuncType, TupleTypes...>, FuncType, TupleTypes...>;
1875
1876 template<typename FuncType, typename... TupleTypes>
1878 enable_if_all_apply_t< apply_return_vector_t<FuncType, TupleTypes...>, FuncType, TupleTypes...>;
1879
1880 template<typename FuncType, typename... TupleTypes>
1882 std::common_type_t<apply_return_t<FuncType, TupleTypes>...>>;
1883
1884 template<typename FuncType, typename... ArgTypes>
1885 types::tuple_if_all_apply_t<FuncType, ArgTypes...>
1886 apply_tuple(FuncType&& f, ArgTypes&&... args)
1887 {
1888 return { std::apply(f, args) ... };
1889 }
1890
1891 template<typename FuncType, typename... ArgTypes>
1892 types::vector_if_all_apply_t<FuncType, ArgTypes...>
1893 apply_vector(FuncType&& f, ArgTypes&&... args)
1894 {
1895 using ele_t = types::common_apply_t<FuncType, ArgTypes...>;
1896 return { (ele_t)std::apply(f, args) ... };
1897 }
1898
1899 template<typename FuncType, typename... ArgTypes>
1900 types::array_if_all_apply_t<FuncType, ArgTypes...>
1901 apply_array(FuncType&& f, ArgTypes&&... args)
1902 {
1903 using ele_t = types::common_apply_t<FuncType, ArgTypes...>;
1904 return { (ele_t)std::apply(f, args) ... };
1905 }
1906
1908
1909 // safe_cast_operation - smart type cast and do not detect overflow
1910 template<typename T> struct safe_cast_operation
1911 {
1912 const T& value;
1913 safe_cast_operation(const T& v): value{ v } { }
1914 };
1915
1916 template<numerical_c T> struct safe_cast_operation<T>
1917 {
1919 safe_cast_operation(T v): value{ std::move(v) } { }
1920 };
1921
1922 namespace hidden
1923 {
1924 template<typename T>
1926
1927 template<typename T>
1929 };
1930
1931 template<typename T>
1932 concept safe_co_c = hidden::st_safe_cast_operation<std::remove_cvref_t<T>>::value;
1933
1934 template<typename T>
1936
1937 template<typename L, typename R>
1938 constexpr auto operator+(safe_cast_operation<L> const& a,
1939 safe_cast_operation<R> const& b) noexcept
1940 {
1941 if constexpr(numerical_c<L> && numerical_c<R>)
1942 {
1943 using r_t = common_signed_t<L, R>;
1944
1945 auto aa = numeric_cast<r_t>(a.value);
1946 auto bb = numeric_cast<r_t>(b.value);
1947
1948 if(aa.has_value() && bb.has_value())
1949 return aa.value() + bb.value();
1950 else
1951 {
1952 std::cout << "In ADDITION: ("
1953 << a.value << ")(" << Cpg_GetTypeName(L) << ") + ("
1954 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
1955
1956 throw std::runtime_error("Integer Addition - Casting failed!");
1957 }
1958 }
1959 else
1960 return a.value + b.value;
1961 }
1962
1963 template<typename L, typename R>
1964 constexpr auto operator-(safe_cast_operation<L> const& a,
1965 safe_cast_operation<R> const& b) noexcept
1966 {
1967 if constexpr(numerical_c<L> && numerical_c<R>)
1968 {
1969 using r_t = common_signed_t<L, R>;
1970
1971 auto aa = numeric_cast<r_t>(a.value);
1972 auto bb = numeric_cast<r_t>(b.value);
1973
1974 if(aa.has_value() && bb.has_value())
1975 return aa.value() - bb.value();
1976 else
1977 {
1978 std::cout << "In SUBTRACTION: ("
1979 << a.value << ")(" << Cpg_GetTypeName(L) << ") - ("
1980 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
1981
1982 throw std::runtime_error("Integer Subtraction - Casting failed!");
1983 }
1984 }
1985 else
1986 return a.value + b.value;
1987 }
1988
1989 template<typename L, typename R>
1990 constexpr auto operator*(safe_cast_operation<L> const& a,
1991 safe_cast_operation<R> const& b) noexcept
1992 {
1993 if constexpr(numerical_c<L> && numerical_c<R>)
1994 {
1995 using r_t = common_signed_t<L, R>;
1996
1997 auto aa = numeric_cast<r_t>(a.value);
1998 auto bb = numeric_cast<r_t>(b.value);
1999
2000 if(aa.has_value() && bb.has_value())
2001 return aa.value() * bb.value();
2002 else
2003 {
2004 std::cout << "In ADDITION: ("
2005 << a.value << ")(" << Cpg_GetTypeName(L) << ") * ("
2006 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
2007
2008 throw std::runtime_error("Integer Multiplication - Casting failed!");
2009 }
2010 }
2011 else
2012 return a.value + b.value;
2013 }
2014
2015 template<typename L, typename R>
2016 constexpr auto operator/(safe_cast_operation<L> const& a,
2017 safe_cast_operation<R> const& b) noexcept
2018 {
2019 if constexpr(numerical_c<L> && numerical_c<R>)
2020 {
2021 using r_t = common_signed_t<L, R>;
2022
2023 auto aa = numeric_cast<r_t>(a.value);
2024 auto bb = numeric_cast<r_t>(b.value);
2025
2026 if(aa.has_value() && bb.has_value())
2027 return aa.value() / bb.value();
2028 else
2029 {
2030 std::cout << "In DIVISION: ("
2031 << a.value << ")(" << Cpg_GetTypeName(L) << ") / ("
2032 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
2033
2034 throw std::runtime_error("Integer Division - Casting failed!");
2035 }
2036 }
2037 else
2038 return a.value + b.value;
2039 }
2040
2041 template<non_safe_co_c L, typename R>
2042 constexpr auto operator+(L&& a, safe_cast_operation<R> const& b)
2043 {
2044 return safe_cast_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) + b;
2045 }
2046
2047 template<typename L, non_safe_co_c R>
2048 constexpr auto operator+(safe_cast_operation<L> const& a, R&& b)
2049 {
2050 return a + safe_cast_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2051 }
2052
2053 template<non_safe_co_c L, typename R>
2054 constexpr auto operator-(L&& a, safe_cast_operation<R> const& b)
2055 {
2056 return safe_cast_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) - b;
2057 }
2058
2059 template<typename L, non_safe_co_c R>
2060 constexpr auto operator-(safe_cast_operation<L> const& a, R&& b)
2061 {
2062 return a - safe_cast_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2063 }
2064
2065 template<non_safe_co_c L, typename R>
2066 constexpr auto operator*(L&& a, safe_cast_operation<R> const& b)
2067 {
2068 return safe_cast_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) * b;
2069 }
2070
2071 template<typename L, non_safe_co_c R>
2072 constexpr auto operator*(safe_cast_operation<L> const& a, R&& b)
2073 {
2074 return a * safe_cast_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2075 }
2076
2077 template<non_safe_co_c L, typename R>
2078 constexpr auto operator/(L&& a, safe_cast_operation<R> const& b)
2079 {
2080 return safe_cast_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) / b;
2081 }
2082
2083 template<typename L, non_safe_co_c R>
2084 constexpr auto operator/(safe_cast_operation<L> const& a, R&& b)
2085 {
2086 return a / safe_cast_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2087 }
2088
2090
2091 // safe_integral_operation - detect integer overflow and smart type cast
2092 template<typename T> struct safe_integral_operation
2093 {
2094 const T& value;
2095 safe_integral_operation(const T& v): value{ v } { }
2096 };
2097
2098 template<numerical_c T> struct safe_integral_operation<T>
2099 {
2101 safe_integral_operation(T v): value{ std::move(v) } { }
2102 };
2103
2104 namespace hidden
2105 {
2106 template<typename T>
2108
2109 template<typename T>
2111 };
2112
2113 template<typename T>
2114 concept safe_io_c = hidden::st_safe_integral_operation<std::remove_cvref_t<T>>::value;
2115
2116 template<typename T>
2118
2119 template<typename L, typename R>
2120 constexpr auto operator+(safe_integral_operation<L> const& a,
2122 {
2123 if constexpr(std::integral<L> && std::integral<R>)
2124 {
2125 using r_t = common_signed_t<L, R>;
2126
2127 // auto aa = numeric_cast<r_t>(a.value);
2128 // auto bb = numeric_cast<r_t>(b.value);
2129
2130 auto [aa, bb] = signed_cast(a.value, b.value);
2131
2132 if(!aa.has_value() || !bb.has_value())
2133 {
2134 std::cout << "In ADDITION: ("
2135 << a.value << ")(" << Cpg_GetTypeName(L) << ") + ("
2136 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
2137
2138 throw std::runtime_error("Integer Addition - Casting failed!");
2139 }
2140
2141 r_t result = aa.value() + bb.value();
2142
2143 if( (a.value > 0 && b.value > 0 && result < 0)
2144 || (a.value < 0 && b.value < 0 && result > 0) )
2145 {
2146 std::cout << "In ADDITION: ("
2147 << a.value << ")(" << Cpg_GetTypeName(L) << ") + ("
2148 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
2149
2150 throw std::runtime_error("Integer Addition - Overflow!");
2151 }
2152 else
2153 return result;
2154 }
2155 else
2156 return a.value + b.value;
2157 }
2158
2159 template<typename L, typename R>
2160 constexpr auto operator-(safe_integral_operation<L> const& a,
2162 {
2163 if constexpr(std::integral<L> && std::integral<R>)
2164 {
2165 using r_t = common_signed_t<L, R>;
2166
2167 auto aa = numeric_cast<r_t>(a.value);
2168 auto bb = numeric_cast<r_t>(b.value);
2169
2170 if(!aa.has_value() || !bb.has_value())
2171 {
2172 std::cout << "In SUBTRACTION: ("
2173 << a.value << ")(" << Cpg_GetTypeName(L) << ") - ("
2174 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
2175
2176 throw std::runtime_error("Integer Subtraction - Casting failed!");
2177 }
2178
2179 bb = -bb.value();
2180 r_t result = aa.value() + bb.value();
2181
2182 if( (aa.value() > 0 && bb.value() > 0 && result < 0) ||
2183 (aa.value() < 0 && bb.value() < 0 && result > 0) )
2184 {
2185 std::cout << "In SUBTRACTION: ("
2186 << a.value << ")(" << Cpg_GetTypeName(L) << ") - ("
2187 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
2188
2189 throw std::runtime_error("Integer Subtraction - Overflow!");
2190 }
2191 else
2192 return result;
2193 }
2194 else
2195 return a.value - b.value;
2196 }
2197
2198 template<typename L, typename R>
2199 constexpr auto operator*(safe_integral_operation<L> const& a,
2201 {
2202 if constexpr(std::integral<L> && std::integral<R>)
2203 {
2204 using r_t = common_signed_t<L, R>;
2205
2206 auto aa = numeric_cast<r_t>(a.value);
2207 auto bb = numeric_cast<r_t>(b.value);
2208
2209 if(!aa.has_value() || !bb.has_value())
2210 {
2211 std::cout << "In MULTIPLICATION: ("
2212 << a.value << ")(" << Cpg_GetTypeName(L) << ") * ("
2213 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
2214
2215 throw std::runtime_error("Integer Multiplication - Casting failed!");
2216 }
2217
2218 r_t result = aa.value() * bb.value();
2219
2220 if(bb.value() ==0)
2221 return result;
2222 else if(result / bb.value() == aa.value())
2223 return result;
2224 else
2225 {
2226 std::cout << "In MULTIPLICATION: ("
2227 << a.value << ")(" << Cpg_GetTypeName(L) << ") * ("
2228 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
2229
2230 throw std::runtime_error("Integer multiplication - Overflow!");
2231 }
2232 }
2233 else
2234 return a.value * b.value;
2235 }
2236
2237 template<typename L, typename R>
2238 constexpr auto operator/(safe_integral_operation<L> const& a,
2240 {
2241 if constexpr(std::integral<L> && std::integral<R>)
2242 {
2243 if(b.value != 0)
2244 {
2245 using r_t = common_signed_t<L, R>;
2246
2247 auto aa = numeric_cast<r_t>(a.value);
2248 auto bb = numeric_cast<r_t>(b.value);
2249
2250 if(aa.has_value() && bb.has_value())
2251 return aa.value() / bb.value();
2252 else
2253 {
2254 std::cout << "In DIVISION: ("
2255 << a.value << ")(" << Cpg_GetTypeName(L) << ") / ("
2256 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
2257
2258 throw std::runtime_error("Integer Division - Casting failed!");
2259 }
2260 }
2261 else
2262 {
2263 std::cout << "In Division: ("
2264 << a.value << ")(" << Cpg_GetTypeName(L) << ") / ("
2265 << b.value << ")(" << Cpg_GetTypeName(R) << ")" << std::endl;
2266
2267 throw std::runtime_error("Integer Division By Zero!");
2268 }
2269 }
2270 else
2271 return a.value / b.value;
2272 }
2273
2274 template<non_safe_io_c L, typename R>
2275 constexpr auto operator+(L&& a, safe_integral_operation<R> const& b)
2276 {
2277 return safe_integral_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) + b;
2278 }
2279
2280 template<typename L, non_safe_io_c R>
2281 constexpr auto operator+(safe_integral_operation<L> const& a, R&& b)
2282 {
2283 return a + safe_integral_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2284 }
2285
2286 template<non_safe_io_c L, typename R>
2287 constexpr auto operator-(L&& a, safe_integral_operation<R> const& b)
2288 {
2289 return safe_integral_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) - b;
2290 }
2291
2292 template<typename L, non_safe_io_c R>
2293 constexpr auto operator-(safe_integral_operation<L> const& a, R&& b)
2294 {
2295 return a - safe_integral_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2296 }
2297
2298 template<non_safe_io_c L, typename R>
2299 constexpr auto operator*(L&& a, safe_integral_operation<R> const& b)
2300 {
2301 return safe_integral_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) * b;
2302 }
2303
2304 template<typename L, non_safe_io_c R>
2305 constexpr auto operator*(safe_integral_operation<L> const& a, R&& b)
2306 {
2307 return a * safe_integral_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2308 }
2309
2310 template<non_safe_io_c L, typename R>
2311 constexpr auto operator/(L&& a, safe_integral_operation<R> const& b)
2312 {
2313 return safe_integral_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) / b;
2314 }
2315
2316 template<typename L, non_safe_io_c R>
2317 constexpr auto operator/(safe_integral_operation<L> const& a, R&& b)
2318 {
2319 return a / safe_integral_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2320 }
2321
2322 // safe_numerical_operation - detect numerical overflow and smart type cast
2323 template<typename T> struct safe_numerical_operation
2324 {
2325 const T& value;
2326 safe_numerical_operation(const T& v): value{ v } { }
2327 };
2328
2329 template<numerical_c T> struct safe_numerical_operation<T>
2330 {
2332 safe_numerical_operation(T v): value{ std::move(v) } { }
2333 };
2334
2335 namespace hidden
2336 {
2337 template<typename T>
2339
2340 template<typename T>
2342 };
2343
2344 template<typename T>
2345 concept safe_no_c = hidden::st_safe_numerical_operation<std::remove_cvref_t<T>>::value;
2346
2347 template<typename T>
2349
2350 template<typename L, typename R>
2353 {
2354 if constexpr(std::integral<L> && std::integral<R>)
2355 {
2358 }
2359 else if constexpr(std::floating_point<L> && std::floating_point<R>)
2360 {
2361 using R_t = common_signed_t<L, R>;
2362
2363 R_t result = static_cast<R_t>(a.value) + static_cast<R_t>(b.value);
2364
2365 if(check_operation_validity(result))
2366 return result;
2367 else
2368 {
2369 std::cout << "Floating-point Addition accuracy failure!"<< std::endl;
2370
2371 std::cout << "In ADDITION: "
2372 << a.value << " (" << Cpg_GetTypeName(L) << ") + "
2373 << b.value << " (" << Cpg_GetTypeName(R) << ")" << std::endl;
2374
2375 std::cout <<"Possibly floating point operation error!" << std::endl;
2376
2377 throw std::runtime_error("binary addition failure");
2378 }
2379
2380 // for compiler type parsing
2381 return R_t{};
2382 }
2383 else
2384 return a.value + b.value;
2385 }
2386
2387 template<typename L, typename R>
2390 {
2391 if constexpr(std::integral<L> && std::integral<R>)
2392 {
2395 }
2396 else if constexpr(std::floating_point<L> && std::floating_point<R>)
2397 {
2398 using R_t = common_signed_t<L, R>;
2399
2400 R_t result = static_cast<R_t>(a.value) - static_cast<R_t>(b.value);
2401
2402 if(check_operation_validity(result))
2403 return result;
2404 else
2405 {
2406 std::cout << "Floating-point Subtraction accuracy failure!"<< std::endl;
2407 std::cout << "In SUBTRACTION: "
2408 << a.value << " (" << Cpg_GetTypeName(L) << ") - "
2409 << b.value << " (" << Cpg_GetTypeName(R) << ")" << std::endl;
2410
2411 std::cout <<"Possibly floating point operation error!" << std::endl;
2412
2413 throw std::runtime_error("binary subtraction failure");
2414 }
2415
2416 // for compiler type parsing
2417 return R_t{};
2418 }
2419 else
2420 return a.value - b.value;
2421 }
2422
2423 template<typename L, typename R>
2426 {
2427 if constexpr(std::integral<L> && std::integral<R>)
2428 {
2429 return
2431 }
2432 else if constexpr(std::floating_point<L> && std::floating_point<R>)
2433 {
2434 using R_t = common_signed_t<L, R>;
2435
2436 R_t result = static_cast<R_t>(a.value)
2437 * static_cast<R_t>(b.value);
2438
2439 if(check_operation_validity(result))
2440 return result;
2441 else
2442 {
2443 std::cout << "Floating-point Mulitiplication accuracy failure!"<< std::endl;
2444
2445 std::cout << "In MULTIPLICATION: "
2446 << a.value << " (" << Cpg_GetTypeName(L) << ") * "
2447 << b.value << " (" << Cpg_GetTypeName(R) << ")" << std::endl;
2448
2449 std::cout <<"Possibly floating point operation error!" << std::endl;
2450
2451 throw std::runtime_error("binary multiplication failure");
2452 }
2453
2454 // for compiler type parsing
2455 return R_t{};
2456 }
2457 else
2458 return a.value * b.value;
2459 }
2460
2461 template<typename L, typename R>
2464 {
2465 if constexpr(std::integral<L> && std::integral<R>)
2466 {
2469 }
2470 else if constexpr(std::floating_point<L> && std::floating_point<R>)
2471 {
2472 using R_t = common_signed_t<L, R>;
2473
2474 if(b.value != 0)
2475 {
2476 R_t result = static_cast<R_t>(a.value) / static_cast<R_t>(b.value);
2477
2478 if(check_operation_validity(result))
2479 return result;
2480 }
2481
2482 std::cout << "Floating-point Division by Zero!"<< std::endl;
2483
2484 std::cout << "In DIVISION: "
2485 << a.value << " (" << Cpg_GetTypeName(L) << ") / "
2486 << b.value << " (" << Cpg_GetTypeName(R) << ")" << std::endl;
2487
2488 throw std::runtime_error("Division by Zero");
2489
2490 // for compiler type parsing
2491 return R_t{};
2492 }
2493 else
2494 return a.value / b.value;
2495 }
2496
2497 template<non_safe_no_c L, typename R>
2498 constexpr auto operator+(L&& a, safe_numerical_operation<R> const& b)
2499 {
2500 return safe_numerical_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) + b;
2501 }
2502
2503 template<typename L, non_safe_no_c R>
2504 constexpr auto operator+(safe_numerical_operation<L> const& a, R&& b)
2505 {
2506 return a + safe_numerical_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2507 }
2508
2509 template<non_safe_no_c L, typename R>
2510 constexpr auto operator-(L&& a, safe_numerical_operation<R> const& b)
2511 {
2512 return safe_numerical_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) - b;
2513 }
2514
2515 template<typename L, non_safe_no_c R>
2516 constexpr auto operator-(safe_numerical_operation<L> const& a, R&& b)
2517 {
2518 return a - safe_numerical_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2519 }
2520
2521 template<non_safe_no_c L, typename R>
2522 constexpr auto operator*(L&& a, safe_numerical_operation<R> const& b)
2523 {
2524 return safe_numerical_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) * b;
2525 }
2526
2527 template<typename L, non_safe_no_c R>
2528 constexpr auto operator*(safe_numerical_operation<L> const& a, R&& b)
2529 {
2530 return a * safe_numerical_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2531 }
2532
2533 template<non_safe_no_c L, typename R>
2534 constexpr auto operator/(L&& a, safe_numerical_operation<R> const& b)
2535 {
2536 return safe_numerical_operation<std::remove_cvref_t<L>>(std::forward<L>(a)) / b;
2537 }
2538
2539 template<typename L, non_safe_no_c R>
2540 constexpr auto operator/(safe_numerical_operation<L> const& a, R&& b)
2541 {
2542 return a / safe_numerical_operation<std::remove_cvref_t<R>>(std::forward<R>(b));
2543 }
2544
2545 // safe binary operation, if CPG_SAFE_NUMERICL_OPERATIONS=1,
2546 // detect overflow and "integer division by zero"
2547 // otherwise, safe cast for integeral numbers
2548 template<long long DebugMode=2, typename T=int>
2549 constexpr auto sbo(T&& value) noexcept(!cpg::bDetectOverFlow)
2550 {
2551 if constexpr(DebugMode == 1)
2552 return safe_integral_operation<std::remove_cvref_t<T>>(std::forward<T>(value));
2553 else if constexpr(DebugMode == 2)
2554 return safe_numerical_operation<std::remove_cvref_t<T>>(std::forward<T>(value));
2555 else
2556 return safe_cast_operation<std::remove_cvref_t<T>>(std::forward<T>(value));
2557 }
2558
2559 namespace hidden
2560 {
2561 template<typename... Types>
2563
2564 template<>
2566
2567 template<typename P, typename... Types>
2568 struct st_all_same<P, Types...>: std::bool_constant<all_same_c<P, Types...>>{ };
2569 }
2570 // end of namespace hidden
2571
2572 template<typename... Types>
2573 concept all_the_same_c = hidden::st_all_same<Types...>::value;
2574
2575 template<typename P, typename... Types>
2576 concept all_same_flat_c = all_same_c< std::remove_cvref_t<P>, std::remove_cvref_t<Types>...>;
2577
2578 template<typename... Types>
2580
2581 namespace hidden
2582 {
2583 // [int, short, float, short] = (int != short) && (int != float) && (int != short)
2584 template<typename P, typename... Types>
2585 concept partial_different_c = ( !std::same_as<P, Types> && ... );
2586
2587 template<typename P, typename... Types>
2588 consteval bool fn_all_different()
2589 {
2590 if constexpr(sizeof...(Types) == 0)
2592 else
2593 return partial_different_c<P, Types...> && fn_all_different<Types...>();
2594 }
2595
2596 template<typename T, typename S>
2598
2599 template< template<typename, typename...> class ContainerType,
2600 typename T1, typename T2, typename... Tails>
2602 < ContainerType<T1, Tails...>, ContainerType<T2, Tails...>> : std::true_type { };
2603
2604 template<typename T>
2606
2607 template<typename T>
2608 struct st_is_vector<std::vector<T>>: std::true_type { };
2609
2610 template<typename T>
2612 {
2613 using type = no_type;
2614 };
2615
2616 template< template<typename, typename...> class ContainerType,
2617 typename T, typename... Types>
2618 struct st_first_element< ContainerType<T, Types...> >
2619 {
2620 using type = T;
2621 };
2622
2623 template< template<typename, auto...> class ContainerType,
2624 typename T, auto... Values>
2625 struct st_first_element< ContainerType<T, Values...> >
2626 {
2627 using type = T;
2628 };
2629
2630 template< template<typename, std::size_t> class ContainerType,
2631 typename T, std::size_t N>
2632 struct st_first_element< ContainerType<T, N> >
2633 {
2634 using type = T;
2635 };
2636 }
2637 // end of namespace hidden
2638
2639 template<typename T>
2640 concept vector_c = hidden::st_is_vector<std::remove_cvref_t<T>>::value;
2641
2642 template<typename T>
2644
2645 template<typename T, typename S>
2647 hidden::st_same_container<std::remove_cvref_t<T>, std::remove_cvref_t<S>>::value;
2648
2649 template<typename P, typename... Types>
2651
2652 template<typename P, typename... Types>
2653 concept all_different_flat_c = all_different_c< std::remove_cvref_t<P>, std::remove_cvref_t<Types>...>;
2654
2655 template<typename P, typename Q, typename... Types>
2656 concept partially_different_c = !all_same_c<P, Q, Types...> && !all_different_c<P, Q, Types...>;
2657
2658 template<typename P, typename Q, typename... Types>
2660 std::remove_cvref_t<Q>, std::remove_cvref_t<Types>...>;
2661
2662 template<auto... Indices>
2663 requires all_the_same_c<decltype(Indices)...>
2664 using sequence =
2665 std::integer_sequence<std::common_type_t<std::remove_cvref_t<decltype(Indices)>...>, Indices...>;
2666
2667 template<typename Type> // Type = char, const_ptr_t<char> = const char* - pointer to const char
2668 using const_ptr_t = std::add_pointer_t<std::add_const_t<Type>>;
2669
2670 template<typename T>
2671 constexpr decltype(auto) decay_value(T&& value) noexcept
2672 {
2673 if constexpr( std::is_function_v<std::remove_reference_t<T>>
2674 || std::is_array_v<std::remove_reference_t<T>> )
2675 {
2676 return static_cast<std::decay_t<std::remove_reference_t<T>>>(value);
2677 }
2678 else
2679 {
2680 return std::forward<T>(value);
2681 }
2682 }
2683
2684 template< template<typename...> class ContainerType, typename... ArgTypes>
2685 constexpr auto create_container(ArgTypes&&... args) noexcept
2686 {
2687 return ContainerType{ decay_value(std::forward<ArgTypes>(args) )... };
2688 }
2689
2690 template< template<typename, auto> class ContainerType,
2691 all_the_same_flat_c... ArgTypes>
2692 constexpr auto create_container(ArgTypes&&... args) noexcept
2693 {
2694 return ContainerType{ decay_value(std::forward<ArgTypes>(args) )... };
2695 }
2696
2697 template< all_the_same_flat_c... ArgTypes>
2698 constexpr auto make_array(ArgTypes&&... args) noexcept
2699 {
2700 return std::array{ decay_value(std::forward<ArgTypes>(args) )... };
2701 }
2702
2703 template< typename... ArgTypes>
2704 constexpr auto make_tuple(ArgTypes&&... args) noexcept
2705 {
2706 return std::make_tuple(std::forward<ArgTypes>(args)...);
2707 }
2708
2709 namespace hidden
2710 {
2711 template<typename> struct st_is_type_container: std::false_type { };
2712
2713 template<typename... Types>
2715
2716 } // end of namespace hdden
2717
2718 template<typename T>
2719 concept type_container_c = hidden::st_is_type_container<T>::value;
2720
2721 template<typename T>
2722 concept non_type_container_c = !hidden::st_is_type_container<T>::value;
2723
2724 namespace hidden
2725 {
2726 template<typename A, typename B>
2728 {
2729 using type = no_type;
2730 };
2731
2732 template<numerical_c A, numerical_c B>
2734 {
2736 };
2737
2738 template<numerical_c A, numerical_c B>
2739 struct st_common_vector< std::vector<A>, std::vector<B> >
2740 {
2741 using type = std::vector< typename st_common_vector<A, B>::type >;
2742 };
2743
2744 template<vector_c A, vector_c B>
2745 struct st_common_vector< std::vector<A>, std::vector<B> >
2746 {
2747 using type = std::vector< typename st_common_vector<A, B>::type >;
2748 };
2749
2750 template<numerical_c A, numerical_c B>
2751 struct st_common_vector< std::vector<A>, B >
2752 {
2753 using type = std::vector< typename st_common_vector<A, B>::type >;
2754 };
2755
2756 template<numerical_c A, numerical_c B>
2757 struct st_common_vector< A, std::vector<B> >
2758 {
2759 using type = std::vector< typename st_common_vector<A, B>::type >;
2760 };
2761
2762 template<vector_c A, numerical_c B>
2763 struct st_common_vector< std::vector<A>, B >
2764 {
2765 using type = std::vector< typename st_common_vector<A, B>::type >;
2766 };
2767
2768 template<numerical_c A, vector_c B>
2769 struct st_common_vector< A, std::vector<B> >
2770 {
2771 using type = std::vector< typename st_common_vector<A, B>::type >;
2772 };
2773
2774 template<typename A, typename B, std::size_t N>
2775 struct st_common_vector<std::vector<std::array<A, N>>, std::vector<std::array<B, N>> >
2776 {
2777 using type = std::vector< std::array<typename st_common_vector<A, B>::type, N> >;
2778 };
2779
2780 template<numerical_c A, typename B, std::size_t N>
2781 struct st_common_vector<A, std::vector<std::array<B, N>> >
2782 {
2783 using type = std::vector< std::array<typename st_common_vector<A, B>::type, N> >;
2784 };
2785
2786 template<typename A, numerical_c B, std::size_t N>
2787 struct st_common_vector<std::vector<std::array<A, N>>, B>
2788 {
2789 using type = std::vector< std::array<typename st_common_vector<A, B>::type, N> >;
2790 };
2791
2792 template<numerical_c A, numerical_c B, std::size_t N>
2793 struct st_common_vector<std::vector<std::array<A, N>>, std::array<B, N> >
2794 {
2795 using type = std::vector< std::array<typename st_common_vector<A, B>::type, N> >;
2796 };
2797
2798 template<numerical_c A, numerical_c B, std::size_t N>
2799 struct st_common_vector<std::array<A, N>, std::vector<std::array<B, N>> >
2800 {
2801 using type = std::vector< std::array<typename st_common_vector<A, B>::type, N> >;
2802 };
2803 }
2804 // end of namespace hidden
2805
2806 template<typename A, typename B>
2808 typename hidden::st_common_vector<std::remove_cvref_t<A>, std::remove_cvref_t<B>>::type;
2809
2810 template<typename A, typename B>
2812
2813 template<typename A, typename B>
2815
2816 // // FIX-LATER - a = 5;
2817 // template<typename TargetChar = char, typename SourceChar = char>
2818 // std::basic_string<TargetChar> smart_convert( const std::basic_string<SourceChar>& src)
2819 // {
2820 // if constexpr( std::same_as<TargetChar, SourceChar> ) &&
2821 // return src;
2822 // }
2823
2824 // template<typename TagetCharPtr = const char*, typename SourceCharPtr = const char*>
2825 // TagetCharPtr smart_convert(SourceCharPtr ptr)
2826 // {
2827 // return ptr;
2828 // }
2829
2830 template<typename CharType, typename... Types>
2831 std::basic_ostream<CharType>& operator<<(std::basic_ostream<CharType>& os,
2832 const type_container<Types...>& tc);
2833
2834
2836 namespace hidden
2837 {
2838 template<typename CharType, typename Type, typename... Types>
2839 std::basic_ostream<CharType>&
2840 print_type_container(std::basic_ostream<CharType>& os, const type_container<Type, Types...>& tc)
2841 {
2842 if constexpr(sizeof...(Types) == 0)
2843 {
2844 if constexpr(type_container_c<Type>)
2845 os << Type{}; // climax of recursion
2846 else
2847 {
2848 auto type_name = Cpg_GetTypeName(Type);
2849
2850 if constexpr(std::same_as<CharType, wchar_t>)
2851 os << ascii_conversion(type_name);
2852 else
2853 os << type_name;
2854 }
2855
2856 return os;
2857 }
2858 else
2859 {
2860 if constexpr(type_container_c<Type>)
2861 os << Type{}; // climax of recursion
2862 else
2863 {
2864 auto type_name = Cpg_GetTypeName(Type);
2865
2866 if constexpr(std::same_as<CharType, wchar_t>)
2867 os << ascii_conversion(type_name);
2868 else
2869 os << type_name;
2870 }
2871
2872 os << Cpg_CharStr(", ");
2873
2875 }
2876 }
2877
2878 } // end of namespace hidden
2879
2880 template<typename CharType, typename... Types> std::basic_ostream<CharType>&
2881 operator<<(std::basic_ostream<CharType>& os, const type_container<Types...>& tc)
2882 {
2883 if constexpr(sizeof...(Types) == 0)
2884 {
2885 os << Cpg_CharStr("< >");
2886 return os;
2887 }
2888 else
2889 {
2890 os << Cpg_CharStr("< ");
2892 os << Cpg_CharStr(" >");
2893
2894 return os;
2895 }
2896 }
2897
2898 namespace hidden
2899 {
2900 // primary class template - <P, int, short, double> = (P == int) || (P == short) || (P == double)
2901 // determins the count of template parameters
2902 template<typename P, typename... Types> struct st_type_in_container;
2903
2904 // from onward specialization, do not concern about
2905 // template parameter list, but concentrate on template arguments.
2906 template<typename P>
2908 {
2909 static constexpr bool value = false;
2910 };
2911
2912 template<typename P, non_type_container_c Type, typename... Tails>
2913 struct st_type_in_container<P, Type, Tails...>
2914 {
2915 static constexpr bool value = std::same_as<P, Type> ||
2916 st_type_in_container<P, Tails...>::value;
2917 };
2918
2919 template<typename P, typename... Types, typename... Tails>
2920 struct st_type_in_container<P, type_container<Types...>, Tails...>
2921 {
2922 static constexpr bool value = st_type_in_container<P, Types...>::value ||
2923 st_type_in_container<P, Tails...>::value;
2924 };
2925
2926 } // end of namespace hidden
2927
2928 template<typename P, typename... Types>
2929 concept is_in_type_container_c = hidden::st_type_in_container<P, Types...>::value;
2930
2931 namespace hidden
2932 {
2933 // primary class template - determines the count of template parameters
2934 template<typename...> struct st_pop_front_t;
2935
2936 template<>
2938 {
2940 };
2941
2942 template<typename Type, typename... Types>
2943 struct st_pop_front_t<Type, Types...>
2944 {
2945 using type = type_container<Types...>;
2946 };
2947
2948 template<typename... Types>
2949 struct st_pop_front_t< type_container<Types...> >
2950 {
2951 using type = typename st_pop_front_t<Types...>::type;
2952 };
2953
2954 }// end of namespace hidden
2955
2956 template<typename... Types>
2957 using pop_front_t = typename hidden::st_pop_front_t<Types...>::type;
2958
2959 namespace hidden
2960 {
2961 template<typename... LeftTypes>
2963 {
2964 std::cout << left <<" - " << right << std::endl;
2965
2966 return left;
2967 }
2968
2969 template<typename... LeftTypes, typename Head>
2971 {
2972 std::cout << left <<" - " << right << std::endl;
2973 std::cout << "Return: " << left << std::endl;
2974
2975 return left;
2976 }
2977
2978 template<typename... LeftTypes, typename First, typename Second, typename... Tails>
2980 {
2981 std::cout << left <<" - " << right << std::endl;
2982
2983 return fn_pop_back( type_container<LeftTypes..., First>{}, type_container<Second, Tails...>{} );
2984 }
2985
2986 template<typename... Types> struct st_pop_back_t;
2987
2988 template<> struct st_pop_back_t<>
2989 {
2991 };
2992
2993 template<non_type_container_c Type, non_type_container_c... Types>
2994 struct st_pop_back_t<Type, Types...>
2995 {
2996 using type = decltype(fn_pop_back( type_container<>{}, type_container<Type, Types...>{} ));
2997 };
2998
2999 template<typename... Types>
3000 struct st_pop_back_t< type_container<Types...> >
3001 {
3002 using type = decltype(fn_pop_back(type_container<>{}, type_container<Types...>{}));
3003 };
3004
3005 } // end of namespace hidden
3006
3007 template<typename... Types>
3008 using pop_back_t = typename hidden::st_pop_back_t<Types...>::type;
3009
3010 template<typename Type>
3011 concept iterator_available_c = requires { typename Type::iterator; };
3012
3013 template<typename Type>
3014 concept reverse_iterator_available_c = requires { typename Type::reverse_iterator; };
3015
3016 namespace hidden
3017 {
3018 // primary class template
3019 // primary class template determines (1) the template parameter count
3020 // (2) parameter category
3021 // (3) declares struct or class name
3022 // (4) enables default parameter initialization
3023 template<typename T> struct st_stl_container
3024 {
3025 constexpr static bool value = false;
3026 };
3027
3028 template<typename Type, typename... Types,
3029 template<typename, typename...> class ContainerTemplate >
3030 struct st_stl_container< ContainerTemplate<Type, Types...> >
3031 {
3032 static constexpr bool value = iterator_available_c< ContainerTemplate<Type, Types...> >;
3033 };
3034
3035 template<typename T> struct st_std_map_container
3036 {
3037 constexpr static bool value = false;
3038 };
3039
3040 template<typename KeyType, typename ValueType, typename... Types>
3041 struct st_std_map_container<std::map<KeyType, ValueType, Types...>>
3042 {
3043 constexpr static bool value = true;
3044 };
3045
3046 template<typename KeyType, typename ValueType, typename... Types>
3047 struct st_std_map_container<std::unordered_map<KeyType, ValueType, Types...>>
3048 {
3049 constexpr static bool value = true;
3050 };
3051
3052 template<typename T> struct st_tbb_map_container
3053 {
3054 constexpr static bool value = false;
3055 };
3056
3057 template<typename KeyType, typename ValueType, typename... Types>
3058 struct st_tbb_map_container<tbb::concurrent_map<KeyType, ValueType, Types...>>
3059 {
3060 constexpr static bool value = true;
3061 };
3062
3063 template<typename KeyType, typename ValueType, typename... Types>
3064 struct st_tbb_map_container<tbb::concurrent_unordered_map<KeyType, ValueType, Types...>>
3065 {
3066 constexpr static bool value = true;
3067 };
3068
3069 } // end of namespace hidden
3070
3071 template<class T>
3072 concept view_c = // std::ranges::view<T>
3073 std::ranges::range<T> && std::movable<T> && std::ranges::enable_view<T>;
3074
3075 template<class T>
3077
3078 template<typename T>
3079 concept stl_container_c = // MSVC++ 2019, c++latest, MSVC++ 2022
3081
3082 /*
3083 strings library -
3084 https://en.cppreference.com/w/cpp/string
3085
3086 Standard library header - string_view
3087 https://en.cppreference.com/w/cpp/header/string_view
3088
3089 String and character literals (C++)
3090 https://docs.microsoft.com/en-us/cpp/cpp/string-and-character-literals-cpp?view=msvc-170
3091
3092 */
3094 types::type_container<std::string, std::wstring, std::u8string, std::u16string, std::u32string,
3095 std::string_view, std::u8string_view, std::u16string_view, std::u32string_view, std::wstring_view>;
3096
3097 /*
3098 008 - Type Function in Action - is_in_type_container_c
3099 https://www.youtube.com/watch?v=rbl1dlk28_w&list=PLsIvhalfft1EtaiJJRmWKUGG0W1hyUKiw&index=8
3100 */
3101
3102 template<typename P>
3103 concept std_map_c = hidden::st_std_map_container<std::remove_cvref_t<P>>::value;
3104
3105 template<typename P>
3106 concept tbb_map_c = hidden::st_tbb_map_container<std::remove_cvref_t<P>>::value;
3107
3108 template<typename P>
3110
3111 template<typename P>
3114
3115 template<typename P>
3118
3119 namespace hidden
3120 {
3121 template<typename... Types> struct st_make_unique_types;
3122
3123 template<> struct st_make_unique_types<>
3124 {
3126 };
3127
3128 template<typename Type, typename... Types>
3129 struct st_make_unique_types<Type, Types...>
3130 {
3131 // using type = decltype(fn_make_unique_types(type_container<>{}, type_container<Type, Types...>{}));
3132 using type =
3133 typename st_make_unique_types<type_container<>, type_container<Type, Types...>>::type;
3134 };
3135
3136 template<typename... Types>
3138 {
3139 // using type = decltype(fn_make_unique_types(type_container<>{}, type_container<Types...>{}));
3140
3141 using type =
3142 typename st_make_unique_types<type_container<>, type_container<Types...> >::type;
3143 };
3144
3145 template<typename... LeftTypes, typename Head>
3147 {
3148 using type = std::conditional_t< is_in_type_container_c< Head, type_container<LeftTypes...> >,
3149 type_container<LeftTypes...>, type_container<LeftTypes..., Head> >;
3150 };
3151
3152 template<typename... LeftTypes, typename First, typename Second, typename... Tails>
3153 struct st_make_unique_types< type_container<LeftTypes...>,
3154 type_container<First, Second, Tails...> >
3155 {
3156 using new_left_t =
3157 typename st_make_unique_types<type_container<LeftTypes...>, type_container<First> >::type;
3158
3159 using type =
3160 typename st_make_unique_types< new_left_t, type_container<Second, Tails...> >::type;
3161 };
3162
3163 } // end of namespace hidden
3164
3165 template<typename... Types>
3166 using make_unique_types_t = typename hidden::st_make_unique_types<Types...>::type;
3167
3168 // P is a Prototype parameter
3169 template<typename P, typename CharType>
3171 requires (P obj, std::basic_ostream<CharType>& os)
3172 {
3173 os << obj; // Simple Requirements
3174 };
3175
3176 namespace hidden
3177 {
3178 template<typename... Types>
3179 consteval auto fn_type_container_to_variant( types::type_container<Types...> )
3180 {
3181 return std::variant<Types...>{};
3182 }
3183
3184 template<typename... Types>
3185 consteval auto fn_make_unique_variant( std::variant<Types...> ) // std::variant<int, double, int, double, short>
3186 // std::variant<int, double, short>
3187 {
3188 /*
3189 017 - std::variant 3 - - make_unique_types_t 1
3190 https://www.youtube.com/watch?v=26E9z-WmLzc&list=PLsIvhalfft1EtaiJJRmWKUGG0W1hyUKiw&index=17
3191
3192 015 - std::variant 2 - make_unique_types_t 1
3193 https://www.youtube.com/watch?v=JJO5-4aib-4&list=PLsIvhalfft1EtaiJJRmWKUGG0W1hyUKiw&index=15
3194
3195 */
3196 using unique_types = types::make_unique_types_t<std::monostate, Types...>;
3197
3198 return fn_type_container_to_variant( unique_types{} );
3199 }
3200 }
3201 // end of namespace hidden
3202
3203 template<typename VariantType>
3205
3206 template<typename... Types>
3207 auto make_vector_of_variants(Types... args)
3208 {
3209 using variant_t = types::make_unique_variant_t< std::variant<Types...> >;
3210
3211 return std::vector<variant_t>{ args... };
3212 }
3213
3215
3216 namespace hidden
3217 {
3218 template<typename T>
3220
3221 template<typename... Types>
3222 struct st_is_variant<std::variant<Types...>>: std::true_type { };
3223
3224 template<typename T>
3226
3227 template<typename... Types>
3228 struct st_is_tuple<std::tuple<Types...>>: std::true_type { };
3229
3230 template<typename T>
3232
3233 template<typename T, std::size_t N>
3234 struct st_is_std_array< std::array<T, N> >: std::true_type { };
3235
3236 // 013 - if constexpr, type tag dispatch, integral_constant, bool_constant, true_type, false_type
3237 // https://www.youtube.com/watch?v=X_o99tZ1RkE&list=PLsIvhalfft1Fpu1DIMZ-4UVtPp7wnL0Hd&index=14
3238 template<typename T>
3240
3241 template<typename T, std::size_t N>
3242 struct st_is_span< std::span<T, N> >: std::true_type { };
3243
3244 template<typename T>
3246
3247 template<typename T, std::size_t N>
3249
3250 template<typename T>
3252
3253 template<typename T, typename S>
3254 struct st_is_pair<std::pair<T, S>>: std::true_type { };
3255
3257 template<typename T, T START, T END, T STEP, T... Indices>
3258 constexpr auto fn_make_sequence(std::integer_sequence<T, Indices...> seq)
3259 {
3260 if constexpr ( STEP > 0 && START < END ) // [START, END)<STEP - positive>
3261 {
3262 return fn_make_sequence<T, START + STEP, END, STEP>
3263 ( std::integer_sequence<T, Indices..., START>{ });
3264 }
3265 else if constexpr( STEP < 0 && START > END ) // [START, END)<STEP - negative>
3266 {
3267 return fn_make_sequence<T, START + STEP, END, STEP>
3268 ( std::integer_sequence<T, Indices..., START>{ });
3269 }
3270 else
3271 return seq;
3272 }
3273
3274 template<typename T>
3276
3277 template<std::size_t N>
3278 struct st_const_chars<const char[N]>: std::true_type { };
3279
3280 template<std::size_t N>
3281 struct st_const_chars<const wchar_t[N]>: std::true_type { };
3282
3283 template<>
3284 struct st_const_chars<const char*>: std::true_type { };
3285
3286 template<>
3287 struct st_const_chars<const wchar_t*>: std::true_type { };
3288
3289 template<std::size_t N>
3290 struct st_const_chars<const char8_t[N]>: std::true_type { };
3291
3292 template<>
3293 struct st_const_chars<const char8_t*>: std::true_type { };
3294
3295 template<std::size_t N>
3296 struct st_const_chars<const char16_t[N]>: std::true_type { };
3297
3298 template<>
3299 struct st_const_chars<const char16_t*>: std::true_type { };
3300
3301 template<std::size_t N>
3302 struct st_const_chars<const char32_t[N]>: std::true_type { };
3303
3304 template<>
3305 struct st_const_chars<const char32_t*>: std::true_type { };
3306
3308
3309 template<typename T>
3311
3312 template<std::size_t N>
3314
3315 template<std::size_t N>
3316 struct st_non_const_chars<wchar_t[N]>: std::true_type { };
3317
3318 template<>
3320
3321 template<>
3322 struct st_non_const_chars<wchar_t*>: std::true_type { };
3323
3324 template<std::size_t N>
3325 struct st_non_const_chars<char8_t[N]>: std::true_type { };
3326
3327 template<>
3328 struct st_non_const_chars<char8_t*>: std::true_type { };
3329
3330 template<std::size_t N>
3331 struct st_non_const_chars<char16_t[N]>: std::true_type { };
3332
3333 template<>
3334 struct st_non_const_chars<char16_t*>: std::true_type { };
3335
3336 template<std::size_t N>
3337 struct st_non_const_chars<char32_t[N]>: std::true_type { };
3338
3339 template<>
3340 struct st_non_const_chars<char32_t*>: std::true_type { };
3341
3342 }
3343 // end of namespace hidden
3344
3345 template<typename T>
3346 concept const_chars_c = hidden::st_const_chars< std::remove_reference_t<T> >::value;
3347
3348 template<typename T>
3349 concept non_const_chars_c = hidden::st_non_const_chars< std::remove_reference_t<T> >::value;
3350
3351 template<typename T>
3353
3354 template<typename T>
3356
3357 template<typename T, T START, T END, T STEP>
3358 using make_sequence = decltype(
3359 hidden::fn_make_sequence<T, START, END, STEP>( std::integer_sequence<T>{} ) );
3360
3361
3362 template<typename T>
3363 concept variant_c = hidden::st_is_variant<T>::value;
3364
3365 template<typename T>
3367
3368 template<typename T>
3369 concept tuple_c = hidden::st_is_tuple<T>::value;
3370
3371 template<typename T>
3373
3374 template<typename T>
3376
3377 template<typename T>
3378 concept std_array_c = hidden::st_is_std_array<T>::value;
3379
3380 template<typename T>
3382
3383 template<typename T>
3385
3386 template<typename T>
3388
3389 template<typename T>
3391
3392 template<typename T>
3394
3395 template<typename T>
3397
3398 template<typename T> // T가 const, lvalue reference, rvalue reference (X)
3399 concept span_c = hidden::st_is_span<T>::value;
3400
3401 template<typename T> // T가 const, volatile, lvalue reference, rvalue reference (O)
3403
3404 template<typename T> // T가 const, volatile, lvalue reference, rvalue reference (O)
3406
3407 template<typename T>
3409
3410 template<typename T>
3412
3413 template<typename T>
3414 concept c_array_c = hidden::st_is_c_array<T>::value;
3415
3416 template<typename T>
3418
3419 template<typename T>
3420 concept pair_c = hidden::st_is_pair<T>::value;
3421
3422 template<typename T>
3424
3425 template<vector_c... ContainerTypes, auto N = sizeof...(ContainerTypes)>
3426 requires (N > 0)
3427 constexpr auto element_counts_are_the_same(ContainerTypes&&... containers)
3428 {
3429 auto Vs = std::forward_as_tuple(containers...);
3430 auto A_size = std::get<0>(Vs).size();
3431
3432 // N for A, B, C..., e.g. wn. N == 0, get<N>(Vs) == A
3433 return for_stallion<N>([&]<auto...k>(sequence<k...>)
3434 {
3435 return ( (A_size == std::get<k>(Vs).size()) && ... );
3436 });
3437 }
3438
3439 template<std_array_flat_c... ContainerTypes,
3440 auto N = sizeof...(ContainerTypes)> requires (N > 0)
3441 constexpr auto element_counts_are_the_same(ContainerTypes... containers)
3442 {
3443 auto Vs = std::tuple( containers... );
3444
3445 using A_t = std::tuple_element_t<0, decltype(Vs)>;
3446 auto A_size = std::tuple_size_v<A_t>;
3447
3448 // N for A, B, C..., e.g. wn. N == 0, get<N>(Vs) == A
3449 return for_stallion<N>([=]<auto...k>(sequence<k...>)
3450 {
3451 return ( ( A_size ==
3452 std::tuple_size_v< std::tuple_element_t<k, decltype(Vs)> >) && ... );
3453 });
3454 }
3455
3456 template<std::size_t N, vector_c VectorType>
3457 constexpr decltype(auto) make_span(VectorType&& v)
3458 {
3460 return std::span<element_t, N>{v};
3461 }
3462
3463 template<std_array_flat_c ArrayType>
3464 constexpr decltype(auto) make_span(ArrayType&& array)
3465 {
3466 return std::span{ array };
3467 }
3468
3469 template<typename T, std::size_t N>
3470 constexpr decltype(auto) make_span(T(&array)[N])
3471 {
3472 return std::span{ array };
3473 }
3474
3475 // end of namespace hidden
3476
3478 namespace hidden
3479 {
3480 template<typename A, typename B>
3482 {
3483 using type = no_type;
3484 };
3485
3486 template<numerical_c A, numerical_c B>
3488 {
3490 };
3491
3492 template<numerical_c A, numerical_c B, std::size_t N>
3493 struct st_std_common_array< std::array<A, N>, std::array<B, N> >
3494 {
3495 using type = std::array< typename st_std_common_array<A, B>::type, N>;
3496 };
3497
3498 template<std_array_c A, std_array_c B, std::size_t N>
3499 struct st_std_common_array< std::array<A, N>, std::array<B, N> >
3500 {
3501 using type = std::array< typename st_std_common_array<A, B>::type, N>;
3502 };
3503
3504 template<numerical_c A, numerical_c B, std::size_t N>
3505 struct st_std_common_array< std::array<A, N>, B >
3506 {
3507 using type = std::array< typename st_std_common_array<A, B>::type, N>;
3508 };
3509
3510 template<numerical_c A, numerical_c B, std::size_t N>
3511 struct st_std_common_array< A, std::array<B, N> >
3512 {
3513 using type = std::array< typename st_std_common_array<A, B>::type, N>;
3514 };
3515
3516 template<std_array_c A, numerical_c B, std::size_t N>
3517 struct st_std_common_array< std::array<A, N>, B >
3518 {
3519 using type = std::array< typename st_std_common_array<A, B>::type, N>;
3520 };
3521
3522 template<numerical_c A, std_array_c B, std::size_t N>
3523 struct st_std_common_array< A, std::array<B, N> >
3524 {
3525 using type = std::array< typename st_std_common_array<A, B>::type, N>;
3526 };
3527
3529 template<numerical_c A, std_array_c B, std::size_t N>
3530 struct st_std_common_array<std::array<A, N>, std::array<B, N> >
3531 {
3532 using type = std::array< typename st_std_common_array<A, B>::type, N>;
3533 };
3534
3535 template<std_array_c A, numerical_c B, std::size_t N>
3536 struct st_std_common_array<std::array<A, N>, std::array<B, N> >
3537 {
3538 using type = std::array< typename st_std_common_array<A, B>::type, N>;
3539 };
3540
3542
3543 template<numerical_c A, std::size_t M, std_array_c B, std::size_t N>
3544 struct st_std_common_array<std::array<A, M>, std::array<B, N> >
3545 {
3547 using type = std::array< std::array< ele_t, M>, N>;
3548 };
3549
3550 template<std_array_c A, std::size_t M, numerical_c B, std::size_t N>
3551 struct st_std_common_array<std::array<A, M>, std::array<B, N> >
3552 {
3554 using type = std::array< std::array<ele_t, N>, M>;
3555 };
3556
3557 }
3558 // end of namespace hidden
3559
3560 template<typename A, typename B>
3562 typename hidden::st_std_common_array<std::remove_cvref_t<A>, std::remove_cvref_t<B>>::type;
3563
3564 template<typename A, typename B>
3566
3568 template<typename... ArgTypes>
3569 class exit_workhorse: public std::runtime_error
3570 {
3571 private:
3572 std::tuple<ArgTypes...> m_tuple;
3573
3574 public:
3575
3576 exit_workhorse(ArgTypes... args):
3577 std::runtime_error{"From workhorse"},
3578 m_tuple{ std::move(args)...} { }
3579
3580 void please()
3581 {
3582 throw *this; // throw itself!!
3583 }
3584
3585 const auto& tuple() const noexcept
3586 {
3587 return this->m_tuple;
3588 }
3589
3590 virtual ~exit_workhorse(){ }
3591 };
3592
3593 namespace hidden
3594 {
3595 // C++ compiler interprets this function
3596 template<typename T, T START, T END, T STEP>
3598 {
3599 if(START != END)
3600 {
3601 T r = (END - START) % STEP;
3602 T q = (END - START) / STEP;
3603
3604 if( r == 0)
3605 return START + (q - 1) * STEP;
3606 else
3607 return START + q * STEP;
3608 }
3609 else
3610 return START;
3611 }
3612
3613 }
3614 // end of namespace hidden
3615
3616 template<typename T, T START, T END, T STEP, T Index>
3618 {
3619 constexpr static auto start = START;
3620 constexpr static auto value = Index;
3621
3622 constexpr static auto last =
3623 hidden::compute_last_index<T, START, END, STEP>();
3624
3625 constexpr static auto end = END;
3626 constexpr static auto step = STEP;
3627 };
3628
3629 template<typename T, T START, T END, T STEP, T Index>
3630 std::ostream& operator<<(std::ostream& os,
3632 {
3633 os<<"{ type=" << Cpg_GetTypeName(T)
3634 <<" | start(index)=" << item.start
3635 <<" | value(cur. idx)=" << item.value
3636 <<" | last(max idx)=" << item.last
3637 <<" | end(count)=" << item.end
3638 <<" | step(incr'nt)=" << item.step <<" }"; return os;
3639 }
3640
3641 namespace hidden
3642 {
3643 template<auto... Args>
3645
3646 template<>
3648 {
3649 using type = std::integer_sequence<long long>;
3650 };
3651
3652 template<auto END>
3654 {
3655 using no_t = decltype(END);
3656 using type = make_sequence<no_t, (no_t)0, END, 1>;
3657 };
3658
3659 template<auto START, auto END>
3660 struct st_create_sequence<START, END>
3661 {
3662 using no_t = decltype(START);
3663 using type = make_sequence<no_t, START, (no_t)END, START < END ? (no_t)1 : (no_t)-1 >;
3664 };
3665
3666 template<auto START, auto END, auto STEP>
3667 struct st_create_sequence<START, END, STEP>
3668 {
3669 using no_t = decltype(START);
3670 using type = make_sequence<no_t, START, (no_t)END, (no_t)STEP>;
3671 };
3672 }
3673 // end of namespace hidden
3674
3675 template<auto... Indices>
3676 requires (sizeof...(Indices) < 4) || requires // constraints expression
3677 {
3678 requires sizeof...(Indices) == 2; // nested requirements
3679 requires ( std::signed_integral<decltype(Indices)> && ... ); // nested requirements
3680 }
3681 using create_sequence = typename hidden::st_create_sequence<Indices...>::type;
3682
3684
3685 template<typename T, T Row, T Column, T Index>
3687 {
3688 constexpr static T row = Row;
3689 constexpr static T column = Column;
3690 constexpr static T value = Index;
3691 constexpr static T size = Row * Column;
3692 };
3693
3694 template<auto Row, auto Column, auto Index>
3695 using row_column_index = row_column_value<decltype(Row), Row, Column, Index>;
3696
3697 template<typename T, T Height, T Row, T Column, T Index>
3699 {
3700 constexpr static T height = Height;
3701 constexpr static T row = Row;
3702 constexpr static T column = Column;
3703 constexpr static T value = Index;
3704 constexpr static T size = Height * Row * Column;
3705 };
3706
3707 template<auto Height, auto Row, auto Column, auto Index>
3708 using height_row_column_index = height_row_column_value<decltype(Height), Height, Row, Column, Index>;
3709
3710 namespace hidden
3711 {
3712 template<typename T>
3714
3715 template<typename T, T Row, T Column, T Index>
3716 struct st_row_column_value<row_column_value<T, Row, Column, Index>>: std::true_type { };
3717
3718 template<typename T>
3720
3721 template<typename T, T Height, T Row, T Column, T Index>
3722 struct st_height_row_column_value<height_row_column_value<T, Height, Row, Column, Index>>: std::true_type { };
3723 }
3724
3725 template<typename T>
3726 concept row_column_value_c = hidden::st_row_column_value<T>::value;
3727
3728 template<typename T>
3729 concept height_row_column_value_c = hidden::st_height_row_column_value<T>::value;
3730
3731 template<typename CharType, typename T, T Row, T Column, T Index>
3732 std::basic_ostream<CharType>&
3733 operator<<(std::basic_ostream<CharType>& os,
3734 row_column_value<T, Row, Column, Index> const& idx)
3735 {
3736 os << Cpg_CharStr("< ")<< Row
3737 << Cpg_CharStr(", ") << Column
3738 << Cpg_CharStr(", ") << Index
3739 << Cpg_CharStr(", ") << idx.size
3740 << Cpg_CharStr(" >") ; return os;
3741 }
3742
3743 template<typename CharType, typename T, T Height, T Row, T Column, T Index>
3744 std::basic_ostream<CharType>&
3745 operator<<(std::basic_ostream<CharType>& os,
3747 {
3748 os << Cpg_CharStr("< ") << Height
3749 << Cpg_CharStr(", ") << Row
3750 << Cpg_CharStr(", ") << Column
3751 << Cpg_CharStr(", ") << Index
3752 << Cpg_CharStr(", ") << idx.size
3753 << Cpg_CharStr(" >") ; return os;
3754 }
3755
3756 template<std::size_t... Ints, typename FuncType>
3757 auto for_tuple(FuncType&& f, std::index_sequence<Ints...>)
3758 {
3759 return std::tuple{ f(indexer_t<Ints>{})... };
3760 }
3761
3762 template<std::size_t... Ints, typename FuncType>
3763 auto for_tuple(std::index_sequence<Ints...>, FuncType&& f)
3764 {
3765 return std::tuple{ f(indexer_t<Ints>{})... };
3766 }
3767
3768 template<std::size_t N, typename FuncType>
3769 auto for_tuple(FuncType&& f)
3770 {
3771 return for_tuple(f, std::make_index_sequence<N>{});
3772 }
3773
3774 template<std::size_t... Ints, typename FuncType>
3775 auto for_array(FuncType&& f, std::index_sequence<Ints...>)
3776 {
3777 return std::array{ f(indexer_t<Ints>{})... };
3778 }
3779
3780 template<std::size_t... Ints, typename FuncType>
3781 auto for_array(std::index_sequence<Ints...>, FuncType&& f)
3782 {
3783 return std::array{ f(indexer_t<Ints>{})... };
3784 }
3785
3786 template<std::size_t N, typename FuncType>
3787 auto for_array(FuncType&& f)
3788 {
3789 return for_array(f, std::make_index_sequence<N>{});
3790 }
3791
3792 template<std::size_t... Ints, typename FuncType>
3793 auto for_vector(FuncType&& f, std::index_sequence<Ints...>)
3794 {
3795 return std::vector{ f(indexer_t<Ints>{})... };
3796 }
3797
3798 template<std::size_t... Ints, typename FuncType>
3799 auto for_vector(std::index_sequence<Ints...>, FuncType&& f)
3800 {
3801 return std::vector{ f(indexer_t<Ints>{})... };
3802 }
3803
3804 template<std::size_t N, typename FuncType>
3805 auto for_vector(FuncType&& f)
3806 {
3807 return for_vector(f, std::make_index_sequence<N>{});
3808 }
3809
3810 namespace hidden
3811 {
3812 template<typename T, T START, T END, T STEP,
3813 typename WorkType, T... Indices, typename... ArgTypes>
3814 void for_workhorse(WorkType&& work, std::integer_sequence<T, Indices...>, ArgTypes&&... args)
3815 requires requires
3816 {
3817 work(item_index<T, START, END, STEP, START>{}, std::forward<ArgTypes>(args)...);
3818 }
3819 {
3820 ( ... , (void)work(item_index<T, START, END, STEP, Indices>{},
3821 std::forward<ArgTypes>(args)...) );
3822 }
3823
3824 template<typename T, T START, T END, T STEP, typename ContainerType,
3825 typename WorkType, T... Indices, typename... ArgTypes>
3826 void for_workhorse(ContainerType&& container, WorkType&& work,
3827 std::integer_sequence<T, Indices...>, ArgTypes&&... args)
3828 requires requires
3829 {
3831 std::get<START>(std::forward<ContainerType>(container)),
3832 std::forward<ArgTypes>(args)...);
3833 }
3834 {
3835 ( ... , (void)work( item_index<T, START, END, STEP, Indices>{},
3836 std::get<Indices>(std::forward<ContainerType>(container)),
3837 std::forward<ArgTypes>(args)...) );
3838 }
3839
3840 template<typename T, T START, T END, T STEP, typename ContainerType,
3841 typename WorkType, T... Indices, typename... ArgTypes>
3842 void for_workhorse(ContainerType&& container, WorkType&& work,
3843 std::integer_sequence<T, Indices...>, ArgTypes&&... args)
3844 requires requires
3845 {
3846 work( std::get<0>(std::forward<ContainerType>(container)),
3847 std::forward<ArgTypes>(args)...);
3848 }
3849 {
3850 ( ... , (void)work(std::get<Indices>(std::forward<ContainerType>(container)),
3851 std::forward<ArgTypes>(args)...) );
3852 }
3853
3855
3856 template<typename T, T START, T END, T STEP,
3857 typename WorkType, T... Indices, typename... ArgTypes>
3858 constexpr decltype(auto) for_stallion(WorkType&& work,
3859 std::integer_sequence<T, Indices...>, ArgTypes&&... args)
3860 requires requires
3861 {
3863 sequence<Indices...>{}, std::forward<ArgTypes>(args)...);
3864 }
3865 {
3867 sequence<Indices...>{}, std::forward<ArgTypes>(args)...);
3868 }
3869
3870 template<typename T, T START, T END, T STEP,
3871 typename WorkType, T... Indices, typename... ArgTypes>
3872 constexpr decltype(auto) for_stallion(WorkType&& work,
3873 std::integer_sequence<T, Indices...>, ArgTypes&&... args)
3874 requires requires
3875 {
3876 work(sequence<Indices...>{},
3877 item_index<T, START, END, STEP, START>{}, std::forward<ArgTypes>(args)...);
3878 }
3879 {
3880 return work(sequence<Indices...>{},
3881 item_index<T, START, END, STEP, START>{}, std::forward<ArgTypes>(args)...);
3882 }
3883
3884 template<typename T, T START, T END, T STEP,
3885 typename WorkType, T... Indices, typename... ArgTypes>
3886 constexpr decltype(auto) for_stallion(WorkType&& work,
3887 std::integer_sequence<T, Indices...>, ArgTypes&&... args)
3888 requires requires
3889 {
3890 work(sequence<Indices...>{}, std::forward<ArgTypes>(args)...);
3891 }
3892 {
3893 return work(sequence<Indices...>{}, std::forward<ArgTypes>(args)...);
3894 }
3895
3896 template<typename T, T Rows, T Columns>
3898 {
3899 return for_stallion<T, T{}, Rows * Columns, T{1}>( []<auto...k>(sequence<k...>)
3900 {
3901 return std::tuple<row_column_value<T, k / Columns, k % Columns, k> ... >{ };
3902
3903 }, std::make_integer_sequence<T, Rows * Columns>{});
3904 }
3905
3906 template<typename T, T Heights, T Rows, T Columns>
3908 {
3909 return for_stallion<T, T{}, Heights * Rows * Columns, T{1}>( []<auto...k>(sequence<k...>)
3910 {
3911 return std::tuple<height_row_column_value<T,
3912 k / (Rows * Columns), (k % (Rows * Columns))/Columns, (k % (Rows * Columns)) % Columns, k> ... >{ };
3913
3914 }, std::make_integer_sequence<T, Heights * Rows * Columns>{});
3915 }
3916 }
3917 // end of namespace hidden
3918
3919 template<typename T, T Rows, T Columns>
3920 using generate_row_column_value = decltype(hidden::generate_row_column_value<T, Rows, Columns>());
3921
3922 template<auto Rows, auto Columns>
3924 decltype(hidden::generate_row_column_value<decltype(Rows), Rows, Columns>());
3925
3926 template<typename T, T Heights, T Rows, T Columns>
3928 decltype(hidden::generate_height_row_column_value<T, Heights, Rows, Columns>());
3929
3930 template<auto Heights, auto Rows, auto Columns>
3933
3934 namespace hidden
3935 {
3936 template<typename... Ls, typename... Rs, auto... Li, auto... Ri>
3937 constexpr auto tuple_append(std::tuple<Ls...> const& A,
3938 sequence<Li...>, std::tuple<Rs...> const& B, sequence<Ri...>) noexcept
3939 {
3940 if constexpr( all_the_same_flat_c<Ls..., Rs...> )
3941 return std::array{ std::get<Li>(A)..., std::get<Ri>(B)... };
3942 else
3943 return std::tuple{ std::get<Li>(A)..., std::get<Ri>(B)... };
3944 }
3945
3946 template<typename... Ls, typename R, auto... Li, std::size_t N, auto... Ri>
3947 constexpr auto tuple_append(std::tuple<Ls...> const& A,
3948 sequence<Li...>, std::array<R, N> const& B, sequence<Ri...>) noexcept
3949 {
3950 if constexpr( all_the_same_flat_c<Ls..., R> )
3951 return std::array{ std::get<Li>(A)..., std::get<Ri>(B)... };
3952 else
3953 return std::tuple{ std::get<Li>(A)..., std::get<Ri>(B)... };
3954 }
3955
3956 template<typename L, std::size_t N, typename... Rs, auto... Li, auto... Ri>
3957 constexpr auto tuple_append(std::array<L, N> const& A,
3958 sequence<Li...>, std::tuple<Rs...> const& B, sequence<Ri...>) noexcept
3959 {
3960 if constexpr( all_the_same_flat_c<L, Rs...> )
3961 return std::array{ std::get<Li>(A)..., std::get<Ri>(B)... };
3962 else
3963 return std::tuple{ std::get<Li>(A)..., std::get<Ri>(B)... };
3964 }
3965
3966 template<typename L, std::size_t N1, typename R, std::size_t N2, auto... Li, auto... Ri>
3967 constexpr auto tuple_append(std::array<L, N1> const& A,
3968 sequence<Li...>, std::array<R, N2> const& B, sequence<Ri...>) noexcept
3969 {
3970 if constexpr( all_the_same_flat_c<L, R> )
3971 return std::array{ std::get<Li>(A)..., std::get<Ri>(B)... };
3972 else
3973 return std::tuple{ std::get<Li>(A)..., std::get<Ri>(B)... };
3974 }
3975 }
3976 // end of namespace hidden
3977
3978 template<typename... Ls, typename... Rs>
3979 constexpr auto tuple_append(std::tuple<Ls...> const& A, std::tuple<Rs...> const& B) noexcept
3980 {
3981 return hidden::tuple_append(A, create_sequence<sizeof...(Ls)>{},
3982 B, create_sequence<sizeof...(Rs)>{});
3983 }
3984
3985 template<typename... Ls, typename R, std::size_t N2>
3986 constexpr auto tuple_append(std::tuple<Ls...> const& A, std::array<R, N2> const& B) noexcept
3987 {
3988 return hidden::tuple_append(A, create_sequence<sizeof...(Ls)>{},
3990 }
3991
3992 template<typename L, std::size_t N1, typename... Rs>
3993 constexpr auto tuple_append(std::array<L, N1> const& A, std::tuple<Rs...> const& B) noexcept
3994 {
3996 B, create_sequence<sizeof...(Rs)>{});
3997 }
3998
3999 template<typename L, std::size_t N1, typename R, std::size_t N2>
4000 constexpr auto tuple_append(std::array<L, N1> const& A, std::array<R, N2> const& B) noexcept
4001 {
4003 }
4004
4005 template<typename... Ls, neither_array_nor_tuple_c... ArgTypes>
4006 constexpr auto tuple_append(std::tuple<Ls...> const& A, ArgTypes&& ... args) noexcept
4007 {
4008 return for_stallion<sizeof...(Ls)>([&]<auto... ii_>(sequence<ii_...>)
4009 {
4010 if constexpr(all_the_same_flat_c<Ls..., ArgTypes...>)
4011 return std::array{ std::get<ii_>(A)..., std::forward<ArgTypes>(args)... };
4012 else
4013 return std::tuple{ std::get<ii_>(A)..., std::forward<ArgTypes>(args)... };
4014 });
4015 }
4016
4017 template<typename L, std::size_t N, neither_array_nor_tuple_c... ArgTypes>
4018 constexpr auto tuple_append(std::array<L, N> const& A, ArgTypes&& ... args) noexcept
4019 {
4020 return for_stallion<N>([&]<auto... ii_>(sequence<ii_...>)
4021 {
4022 if constexpr(all_the_same_flat_c<L, ArgTypes...>)
4023 return std::array{ std::get<ii_>(A)..., std::forward<ArgTypes>(args)... };
4024 else
4025 return std::tuple{ std::get<ii_>(A)..., std::forward<ArgTypes>(args)... };
4026 });
4027 }
4028
4029 template<neither_array_nor_tuple_c... Types>
4030 constexpr auto tuple_append(Types&&... args) noexcept
4031 {
4032 if constexpr(all_the_same_flat_c<Types...>)
4033 return std::array{std::forward<Types>(args)...};
4034 else
4035 return std::tuple{std::forward<Types>(args)...};
4036 }
4037
4038 // 1.
4039 // P. Provide: container, work, [args...]
4040 // S. Supplied: [index], element, and [args...]
4041 template<typename ContainerType = std::tuple<>,
4042 long long END = std::tuple_size_v<std::remove_cvref_t<ContainerType>>,
4043 typename WorkType = std::tuple<>, typename... ArgTypes>
4044 requires (tuple_flat_c<ContainerType> || std_array_flat_c<ContainerType>)
4045 void for_workhorse(ContainerType&& container, WorkType&& work, ArgTypes&& ... args)
4046 requires requires
4047 {
4048 hidden::for_workhorse<long long, 0ll, END, 1ll>(std::forward<ContainerType>(container),
4049 std::forward<WorkType>(work), make_sequence<long long, 0ll, END, 1ll>{},
4050 std::forward<ArgTypes>(args)... );
4051 }
4052 {
4053 hidden::for_workhorse<long long, 0ll, END, 1ll>(std::forward<ContainerType>(container),
4054 std::forward<WorkType>(work), make_sequence<long long, 0ll, END, 1ll>{},
4055 std::forward<ArgTypes>(args)... );
4056 }
4057
4058 // 2.
4059 // P. Provide: Container Type, work, [args...]
4060 // S. Supplied: indices, [args...]
4061 template<typename ContainerType = std::tuple<>, typename WorkType= std::tuple<>,
4062 long long END = std::tuple_size_v<std::remove_cvref_t<ContainerType>>, typename... ArgTypes>
4063 requires (variant_flat_c<ContainerType>||
4064 tuple_flat_c<ContainerType> ||
4065 std_array_flat_c<ContainerType>||
4066 c_array_flat_c<ContainerType>||
4067 pair_flat_c<ContainerType>)
4068 void for_workhorse(WorkType&& work, ArgTypes&& ... args)
4069 requires requires
4070 {
4071 hidden::for_workhorse<long long, 0ll, END, 1ll>(std::forward<WorkType>(work),
4073 std::forward<ArgTypes>(args)... );
4074 }
4075 {
4076 hidden::for_workhorse<long long, 0ll, END, 1ll>(std::forward<WorkType>(work),
4077 make_sequence<long long, 0ll, END, 1ll>{},
4078 std::forward<ArgTypes>(args)... );
4079 }
4080
4081 // 3.
4082 // P. Provide: END, work, [args...]
4083 // S. Supplied: indices, [args...]
4084 template<int END, typename WorkType, typename... ArgTypes>
4085 void for_workhorse(WorkType&& work, ArgTypes&& ... args)
4086 requires requires
4087 {
4088 hidden::for_workhorse<long long, 0ll, END, 1ll>(std::forward<WorkType>(work),
4090 std::forward<ArgTypes>(args)... );
4091 }
4092 {
4093 hidden::for_workhorse<long long, 0ll, END, 1ll>(std::forward<WorkType>(work),
4094 make_sequence<long long, 0ll, END, 1ll>{},
4095 std::forward<ArgTypes>(args)... );
4096 }
4097
4098 // 4.
4099 // P. Provide: START, END, work, [args...]
4100 // S. Supplied: indices, [args...]
4101 template<long long START, long long END, typename WorkType, typename... ArgTypes>
4102 void for_workhorse(WorkType&& work, ArgTypes&& ... args)
4103 requires requires
4104 {
4105 hidden::for_workhorse<long long, START, END, START < END ? 1ll : -1ll>(std::forward<WorkType>(work),
4106 make_sequence<long long, START, END, START < END ? 1ll : -1ll>{},
4107 std::forward<ArgTypes>(args)... );
4108 }
4109 {
4110 hidden::for_workhorse<long long, START, END, START < END ? 1ll : -1ll>(std::forward<WorkType>(work),
4111 make_sequence<long long, START, END, START < END ? 1ll : -1ll>{},
4112 std::forward<ArgTypes>(args)... );
4113 }
4114
4115 // 5.
4116 // P. Provide: START, END, STEP, work, [args...]
4117 // S. Supplied: indices, [args...]
4118 template<long long START, long long END, long long STEP,
4119 typename WorkType, typename... ArgTypes>
4120 void for_workhorse(WorkType&& work, ArgTypes&& ... args)
4121 requires requires
4122 {
4123 hidden::for_workhorse<long long, START, END, STEP>(std::forward<WorkType>(work),
4125 std::forward<ArgTypes>(args)... );
4126 }
4127 {
4128 hidden::for_workhorse<long long, START, END, STEP>(std::forward<WorkType>(work),
4129 make_sequence<long long, START, END, STEP>{},
4130 std::forward<ArgTypes>(args)... );
4131 }
4132
4134
4135 // 1A. stallion
4136 template<typename ContainerType, typename WorkType= std::tuple<>,
4137 long long END = std::tuple_size_v<std::remove_cvref_t<ContainerType>>, typename... ArgTypes>
4138 requires (variant_flat_c<ContainerType>||
4139 tuple_flat_c<ContainerType> ||
4140 std_array_flat_c<ContainerType>||
4141 c_array_flat_c<ContainerType>||
4142 pair_flat_c<ContainerType>)
4143 constexpr decltype(auto) for_stallion(WorkType&& work, ArgTypes&& ... args)
4144 requires requires
4145 {
4146 hidden::for_stallion<long long, 0ll, END, 1ll>(std::forward<WorkType>(work),
4147 make_sequence<long long, 0ll, END, 1ll>{}, std::forward<ArgTypes>(args)... );
4148 }
4149 {
4150 return hidden::for_stallion<long long, 0ll, END, 1ll>(std::forward<WorkType>(work),
4151 make_sequence<long long, 0ll, END, 1ll>{}, std::forward<ArgTypes>(args)... );
4152 }
4153
4154 // 1B. stallion
4155 template<typename ContainerType, typename WorkType= std::tuple<>,
4156 long long END = std::tuple_size_v<std::remove_cvref_t<ContainerType>>, typename... ArgTypes>
4157 requires (variant_flat_c<ContainerType>||
4158 tuple_flat_c<ContainerType> ||
4159 std_array_flat_c<ContainerType>||
4160 c_array_flat_c<ContainerType>||
4161 pair_flat_c<ContainerType>)
4162 constexpr decltype(auto) for_stallion(ContainerType&& container,
4163 WorkType&& work, ArgTypes&& ... args)
4164 requires requires
4165 {
4166 hidden::for_stallion<long long, 0ll, END, 1ll>(std::forward<WorkType>(work),
4167 make_sequence<long long, 0ll, END, 1ll>{}, std::forward<ArgTypes>(args)... );
4168 }
4169 {
4170 return hidden::for_stallion<long long, 0ll, END, 1ll>(std::forward<WorkType>(work),
4171 make_sequence<long long, 0ll, END, 1ll>{}, std::forward<ArgTypes>(args)... );
4172 }
4173
4174 template<long long END, typename WorkType, typename... ArgTypes>
4175 constexpr decltype(auto) for_stallion(WorkType&& work, ArgTypes&& ... args)
4176 requires requires
4177 {
4178 hidden::for_stallion<long long, 0ll, END, 1ll>(std::forward<WorkType>(work),
4179 make_sequence<long long, 0ll, END, 1ll>{}, std::forward<ArgTypes>(args)... );
4180 }
4181 {
4182 return hidden::for_stallion<long long, 0ll, END, 1ll>(std::forward<WorkType>(work),
4183 make_sequence<long long, 0ll, END, 1ll>{}, std::forward<ArgTypes>(args)... );
4184 }
4185
4186 template<long long START, long long END, typename WorkType, typename... ArgTypes>
4187 constexpr decltype(auto) for_stallion(WorkType&& work, ArgTypes&& ... args)
4188 requires requires
4189 {
4190 hidden::for_stallion<long long, START, END, START < END ? 1ll: -1ll>(std::forward<WorkType>(work),
4191 make_sequence<long long, START, END, START < END ? 1ll: -1ll>{}, std::forward<ArgTypes>(args)... );
4192 }
4193 {
4194 return hidden::for_stallion<long long, START, END, START < END ? 1ll: -1ll>(std::forward<WorkType>(work),
4195 make_sequence<long long, START, END, START < END ? 1ll: -1ll>{}, std::forward<ArgTypes>(args)... );
4196 }
4197
4198 // 8.
4199 // P. Provide: START, END, STEP, work, [args...]
4200 // S. Supplied: indices, [args...]
4201 template<long long START, long long END, long long STEP,
4202 typename WorkType, typename... ArgTypes>
4203 constexpr decltype(auto) for_stallion(WorkType&& work, ArgTypes&& ... args)
4204 requires requires
4205 {
4206 hidden::for_stallion<long long, START, END, STEP>(std::forward<WorkType>(work),
4207 make_sequence<long long, START, END, STEP>{}, std::forward<ArgTypes>(args)... );
4208 }
4209 {
4210 return hidden::for_stallion<long long, START, END, STEP>(std::forward<WorkType>(work),
4211 make_sequence<long long, START, END, STEP>{}, std::forward<ArgTypes>(args)... );
4212 }
4213
4214 template<auto head, auto... tails>
4216 {
4217 return sequence<tails...>{};
4218 }
4219
4220 template<auto left, auto... lefts, auto head, auto... tails>
4222 {
4223 if constexpr(sizeof...(tails) == 0)
4225 else
4227 }
4228
4229 template<auto head, auto... tails>
4231 {
4232 if constexpr(sizeof...(tails)==0)
4233 return head;
4234 else
4235 return head * get_total(sequence<tails...>{});
4236 }
4237
4238 template<auto ii, auto head, auto... tails>
4240 {
4241 if constexpr(ii == 0)
4242 return head;
4243 else
4244 return get<ii-1>(sequence<tails...>{});
4245 }
4246
4247 template<auto... ms, auto...rs>
4249 {
4250 return sequence< get<rs>(mm)...>{};
4251 }
4252
4253 template<auto kk, auto ii = 0, auto... ms, auto head, auto... indices>
4255 {
4256 if constexpr(ii < sizeof...(ms))
4257 {
4258 constexpr auto n = get<ii>(sequence<ms...>{});
4259 return get_index<kk % n, ii + 1>(sequence<head, indices..., kk / n>{}, mm);
4260 }
4261 else
4262 return sequence<indices...>{};
4263 }
4264
4265 template<typename T, T... args>
4266 constexpr auto create_tuple_sequence(std::integer_sequence<T, args...> dimensions)
4267 {
4268 constexpr auto multipliers =
4269 compute_multipliers(sequence<T{1}>{}, dimensions);
4270
4271 constexpr auto total = get_total(dimensions);
4272
4273 return for_stallion<total>([multipliers]<auto...ii>(sequence<ii...>)
4274 {
4275 return std::tuple{ get_index<ii>(sequence<1LL>{}, multipliers) ... };
4276 });
4277 }
4278
4279 namespace hidden
4280 {
4281 template<typename WorkType, typename ... Indices, typename... ArgTypes>
4282 constexpr decltype(auto) for_stallion_tuple(WorkType&& work,
4283 std::tuple<Indices...> indices, ArgTypes&&... args)
4284 requires requires
4285 { work(indices, std::forward<ArgTypes>(args)...); }
4286 {
4287 return work(indices, std::forward<ArgTypes>(args)...);
4288 }
4289 }
4290 // end of namespace hidden
4291
4292 template<long long... Ns, typename WorkType, typename... ArgTypes>
4293 constexpr decltype(auto) for_stallion_tuple(WorkType&& work, ArgTypes&& ... args)
4294 requires requires
4295 {
4296 hidden::for_stallion_tuple(std::forward<WorkType>(work),
4297 create_tuple_sequence(sequence<Ns...>{}), std::forward<ArgTypes>(args)... );
4298 }
4299 {
4300 return hidden::for_stallion_tuple(std::forward<WorkType>(work),
4301 create_tuple_sequence(sequence<Ns...>{}), std::forward<ArgTypes>(args)... );
4302 }
4303
4304 namespace array_tuple_hidden
4305 {
4306 template<tuple_flat_c TupleType>
4307 constexpr decltype(auto) tuple_to_array_recursive(TupleType&& tuple)
4308 {
4309 return for_stallion<decltype(tuple)>([&tuple]<auto...ii>( sequence<ii...> )
4310 {
4311 constexpr bool has_common_type =
4313
4314 if constexpr(has_common_type)
4315 {
4316 using common_t = std::common_type_t< decltype( std::get<ii>(tuple) )... >;
4317
4318 if constexpr(numerical_c<common_t>)
4319 {
4320 using c_t = make_signed_t< common_t >;
4321
4322 auto to_array = []<typename Type>(Type&& e)
4323 {
4324 if constexpr(tuple_flat_c<Type>)
4325 return tuple_to_array_recursive(std::forward<Type>(e));
4326 else
4327 return std::forward<Type>(e);
4328 };
4329
4330 return std::array{ static_cast<c_t>(to_array(std::get<ii>(tuple))) ... };
4331 }
4332 else
4333 {
4334 auto to_array = []<typename Type>(Type&& e)
4335 {
4336 if constexpr(tuple_flat_c<Type>)
4337 return tuple_to_array_recursive(std::forward<Type>(e));
4338 else
4339 return std::forward<Type>(e);
4340 };
4341
4342 return std::array{ to_array(std::get<ii>(tuple)) ... };
4343 }
4344 }
4345 else
4346 {
4347 auto to_array = []<typename Type>(Type&& e)
4348 {
4349 if constexpr(tuple_flat_c<Type>)
4350 return tuple_to_array_recursive(std::forward<Type>(e));
4351 else
4352 return std::forward<Type>(e);
4353 };
4354
4355 return std::tuple{ to_array(std::get<ii>(tuple))... };
4356 }
4357 });
4358 }
4359 // end of tuple_to_array_recursive()
4360
4361 template<tuple_flat_c TupleType>
4362 constexpr decltype(auto) tuple_to_array(TupleType&& tuple)
4363 {
4364 return for_stallion<TupleType>([&tuple]<auto...ii_>( sequence<ii_...> )
4365 {
4366 constexpr bool has_common_type =
4368
4369 if constexpr(has_common_type)
4370 {
4371 using common_t = std::common_type_t< decltype( std::get<ii_>(tuple) )... >;
4372
4373 if constexpr(numerical_c<common_t>)
4374 {
4375 using c_t = make_signed_t<common_t>;
4376
4377 return std::array{ static_cast<c_t>(std::get<ii_>(tuple)) ... };
4378 }
4379 else
4380 {
4381 return std::array{ std::get<ii_>(tuple) ... };
4382 }
4383 }
4384 else
4385 return std::forward<TupleType>(tuple);
4386 });
4387 }
4388 }
4389 // end of namespace array_tuple_hidden
4390
4391 template<tuple_flat_c TupleType>
4392 constexpr decltype(auto) tuple_to_array(TupleType&& tuple)
4393 {
4394 return array_tuple_hidden::tuple_to_array(std::forward<TupleType>(tuple));
4395 }
4396
4397 template<tuple_flat_c TupleType>
4398 constexpr decltype(auto) tuple_to_array_recursive(TupleType&& tuple)
4399 {
4400 return array_tuple_hidden::tuple_to_array_recursive(std::forward<TupleType>(tuple));
4401 }
4402
4403 template<typename... Types>
4404 auto reverse_tuple( std::tuple<Types...> const& tuple)
4405 {
4406 constexpr long long N = sizeof...(Types) - 1;
4407
4408 auto reverse = [&]<auto...i>(sequence<i...>)
4409 {
4410 return std::tuple{ std::get<i>(tuple) ... };
4411 };
4412
4413 return for_stallion<N, -1>(reverse);
4414 }
4415
4416 template<typename Type, std::size_t N>
4417 auto reverse_array( std::array<Type, N> const& array)
4418 {
4419 std::array<Type, N> result = array;
4420
4421 std::reverse(result.begin(), result.end());
4422
4423 return result;
4424 }
4425 }
4426 // end of namespace types
4427
4428} // end of namespace cpg
4429
4430#endif // end of file _CPG_TYPES_HPP
std::atomic< int > count
Definition: 022-mutex.cpp:10
auto & cout
integral_constant< bool, true > true_type
integral_constant< bool, false > false_type
constexpr auto is_same_v
typename enable_if< predicate, ReturnType >::type enable_if_t
Definition: 12_sfinae.cpp:23
debug_exception(std::string message, int lineno, std::string file_name)
Definition: cpg_types.hpp:595
virtual const char * what() const noexcept override
Definition: cpg_types.hpp:608
exit_workhorse(ArgTypes... args)
Definition: cpg_types.hpp:3576
const auto & tuple() const noexcept
Definition: cpg_types.hpp:3585
fold_visitor(auto arg_count, OperationType opr, DelimiterOpen d_open, DelimiterType del, DelimiterClose d_close)
Definition: cpg_types.hpp:393
fold_visitor(auto arg_count, OperationType opr, DelimiterType del)
Definition: cpg_types.hpp:314
#define Cpg_CharStr(asciistr)
Definition: cpg_types.hpp:582
#define Cpg_GetTypeName(type_arg,...)
Definition: cpg_types.hpp:740
std::common_type_t< S, T > common_t
Definition: cpg_bitwise.hpp:79
std::make_signed_t< T > signed_t
Definition: cpg_bitwise.hpp:76
constexpr decltype(auto) tuple_to_array_recursive(TupleType &&tuple)
Definition: cpg_types.hpp:4307
constexpr decltype(auto) tuple_to_array(TupleType &&tuple)
Definition: cpg_types.hpp:4362
no_type fn_apply(...)
constexpr auto fn_pop_back(type_container< LeftTypes... > left, type_container< > right)
Definition: cpg_types.hpp:2962
constexpr auto generate_row_column_value()
Definition: cpg_types.hpp:3897
constexpr auto fn_return_type(FuncType func, type_container< Type, Types... >)
Definition: cpg_types.hpp:833
constexpr decltype(auto) for_stallion_tuple(WorkType &&work, std::tuple< Indices... > indices, ArgTypes &&... args)
Definition: cpg_types.hpp:4282
constexpr auto fn_make_sequence(std::integer_sequence< T, Indices... > seq)
Definition: cpg_types.hpp:3258
no_type safe_apply(...)
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 auto argument_count(FuncType func, type_container< Type, Types... >)
Definition: cpg_types.hpp:844
consteval auto fn_make_unique_variant(std::variant< Types... >)
Definition: cpg_types.hpp:3185
consteval bool fn_all_different()
Definition: cpg_types.hpp:2588
constexpr decltype(auto) for_stallion(WorkType &&work, std::integer_sequence< T, Indices... >, ArgTypes &&... args)
Definition: cpg_types.hpp:3858
constexpr auto generate_height_row_column_value()
Definition: cpg_types.hpp:3907
std::wstring ascii_conversion(std::string const &str)
Definition: cpg_types.hpp:262
no_type array_apply(...)
consteval T compute_last_index()
Definition: cpg_types.hpp:3597
void for_workhorse(WorkType &&work, std::integer_sequence< T, Indices... >, ArgTypes &&... args)
Definition: cpg_types.hpp:3814
std::basic_ostream< CharType > & print_type_container(std::basic_ostream< CharType > &os, const type_container< Type, Types... > &tc)
Definition: cpg_types.hpp:2840
consteval auto fn_type_container_to_variant(types::type_container< Types... >)
Definition: cpg_types.hpp:3179
types::array_if_all_apply_t< FuncType, ArgTypes... > apply_array(FuncType &&f, ArgTypes &&... args)
Definition: cpg_types.hpp:1901
constexpr auto get(nontype_container< arg, args... >) noexcept
Definition: cpg_types.hpp:813
std::basic_ostream< CharType > & operator<<(std::basic_ostream< CharType > &os, cpg::types::cHarsTR const &charstr)
Definition: cpg_types.hpp:288
constexpr bool common_apply_v
Definition: cpg_types.hpp:1847
void print_args_reverse(auto &&... args)
Definition: cpg_types.hpp:562
constexpr decltype(auto) signed_cast(ArgTypes... args)
Definition: cpg_types.hpp:1201
auto raii_create_object(PointerType object_ptr, FuncType func)
Definition: cpg_types.hpp:934
typename hidden::st_pop_front_t< Types... >::type pop_front_t
Definition: cpg_types.hpp:2957
std::vector< std::common_type_t< apply_return_t< FuncType, TupleTypes >... > > apply_return_vector_t
Definition: cpg_types.hpp:1863
make_signed_t< std::common_type_t< std::remove_cvref_t< Types >... > > common_signed_t
Definition: cpg_types.hpp:1012
auto for_vector(FuncType &&f, std::index_sequence< Ints... >)
Definition: cpg_types.hpp:3793
constexpr decltype(auto) make_span(VectorType &&v)
Definition: cpg_types.hpp:3457
types::vector_if_all_apply_t< FuncType, ArgTypes... > apply_vector(FuncType &&f, ArgTypes &&... args)
Definition: cpg_types.hpp:1893
types::type_container< std::string, std::wstring, std::u8string, std::u16string, std::u32string, std::string_view, std::u8string_view, std::u16string_view, std::u32string_view, std::wstring_view > string_containers
Definition: cpg_types.hpp:3095
constexpr auto operator/(safe_cast_operation< L > const &a, safe_cast_operation< R > const &b) noexcept
Definition: cpg_types.hpp:2016
types::tuple_if_all_apply_t< FuncType, ArgTypes... > apply_tuple(FuncType &&f, ArgTypes &&... args)
Definition: cpg_types.hpp:1886
fold_visitor(OperationType) -> fold_visitor< OperationType >
constexpr auto drop_head(sequence< head, tails... >)
Definition: cpg_types.hpp:4215
std::common_type_t< apply_return_t< FuncType, TupleTypes >... > common_apply_t
Definition: cpg_types.hpp:1838
std::index_sequence<(std::size_t) Id,(std::size_t) Ids... > index_t
Definition: cpg_types.hpp:907
typename hidden::st_pop_back_t< Types... >::type pop_back_t
Definition: cpg_types.hpp:3008
std::string type_tO_sTring()
Definition: cpg_types.hpp:618
constexpr decltype(auto) decay_value(T &&value) noexcept
Definition: cpg_types.hpp:2671
constexpr auto compute_multipliers(sequence< left, lefts... > result, sequence< head, tails... >)
Definition: cpg_types.hpp:4221
auto & cast_ref(std::unique_ptr< T[], Deleter > &uptr) noexcept
Definition: cpg_types.hpp:1290
constexpr auto tuple_append(std::tuple< Ls... > const &A, std::tuple< Rs... > const &B) noexcept
Definition: cpg_types.hpp:3979
constexpr decltype(auto) for_stallion(WorkType &&work, ArgTypes &&... args)
Definition: cpg_types.hpp:4143
decltype(generate_height_row_column_value< decltype(Heights), Heights, Rows, Columns >()) create_height_row_column_value_t
Definition: cpg_types.hpp:3932
decltype(hidden::generate_row_column_value< decltype(Rows), Rows, Columns >()) create_row_column_value_t
Definition: cpg_types.hpp:3924
constexpr decltype(auto) numeric_cast(S s)
Definition: cpg_types.hpp:1053
decltype(hidden::fn_make_unique_variant(VariantType{})) make_unique_variant_t
Definition: cpg_types.hpp:3204
typename hidden::st_make_unique_types< Types... >::type make_unique_types_t
Definition: cpg_types.hpp:3166
auto for_tuple(FuncType &&f, std::index_sequence< Ints... >)
Definition: cpg_types.hpp:3757
auto reverse_tuple(std::tuple< Types... > const &tuple)
Definition: cpg_types.hpp:4404
std::enable_if_t< all_apply_v< FuncType, TupleTypes... >, ReturnType > enable_if_all_apply_t
Definition: cpg_types.hpp:1852
make_unsigned_t< std::common_type_t< std::remove_cvref_t< Types >... > > common_unsigned_t
Definition: cpg_types.hpp:1016
enable_if_all_apply_t< apply_return_tuple_t< FuncType, TupleTypes... >, FuncType, TupleTypes... > tuple_if_all_apply_t
Definition: cpg_types.hpp:1870
constexpr auto element_counts_are_the_same(ContainerTypes &&... containers)
Definition: cpg_types.hpp:3427
std::basic_ostream< CharType > & operator>>(std::basic_ostream< CharType > &os, nontype_container< args... > nc) noexcept
Definition: cpg_types.hpp:807
typename hidden::st_create_sequence< Indices... >::type create_sequence
Definition: cpg_types.hpp:3681
auto cast_array(T(&array)[N]) noexcept
Definition: cpg_types.hpp:1685
constexpr bool is_apply_v
Definition: cpg_types.hpp:1841
constexpr auto get_nth_value(std::integer_sequence< Type, Index, Indices... >) noexcept
Definition: cpg_types.hpp:241
constexpr decltype(auto) tuple_to_array(TupleType &&tuple)
Definition: cpg_types.hpp:4392
typename hidden::st_common_container< S, T >::type common_container_t
Definition: cpg_types.hpp:1808
constexpr auto create_container(ArgTypes &&... args) noexcept
Definition: cpg_types.hpp:2685
std::add_pointer_t< std::add_const_t< Type > > const_ptr_t
Definition: cpg_types.hpp:2668
typename hidden::st_first_element< std::remove_cvref_t< T > >::type first_type_t
Definition: cpg_types.hpp:2643
decltype(return_type(std::declval< FuncType >(), Type{})) return_type_t
Definition: cpg_types.hpp:864
std::tuple< apply_return_t< FuncType, TupleTypes > ... > apply_return_tuple_t
Definition: cpg_types.hpp:1855
void for_workhorse(ContainerType &&container, WorkType &&work, ArgTypes &&... args)
Definition: cpg_types.hpp:4045
typename hidden::st_unsigned_type< std::remove_cvref_t< T > >::type make_unsigned_t
Definition: cpg_types.hpp:1008
typename hidden::st_std_common_array< std::remove_cvref_t< A >, std::remove_cvref_t< B > >::type common_std_array_t
Definition: cpg_types.hpp:3562
void print_args_inorder(auto &&... args)
Definition: cpg_types.hpp:544
range(Type) -> range< Type >
constexpr bool all_apply_v
Definition: cpg_types.hpp:1844
constexpr auto check_operation_validity(T &&target)
Definition: cpg_types.hpp:1217
typename hidden::st_common_vector< std::remove_cvref_t< A >, std::remove_cvref_t< B > >::type common_vector_t
Definition: cpg_types.hpp:2808
constexpr auto argument_count(FuncType func, Type)
Definition: cpg_types.hpp:867
enable_if_all_apply_t< void, FuncType, TupleTypes... > void_if_all_apply_t
Definition: cpg_types.hpp:1866
decltype(hidden::generate_row_column_value< T, Rows, Columns >()) generate_row_column_value
Definition: cpg_types.hpp:3920
constexpr auto sbo(T &&value) noexcept(!cpg::bDetectOverFlow)
Definition: cpg_types.hpp:2549
auto for_array(FuncType &&f, std::index_sequence< Ints... >)
Definition: cpg_types.hpp:3775
constexpr auto operator-(safe_cast_operation< L > const &a, safe_cast_operation< R > const &b) noexcept
Definition: cpg_types.hpp:1964
constexpr std::enable_if_t< std::is_same_v< std::remove_reference_t< TargetType >, std::remove_reference_t< _Ty > >, std::remove_reference_t< _Ty > && > smart_move(_Ty &&_Arg) noexcept
Definition: cpg_types.hpp:1274
std::array< std::common_type_t< apply_return_t< FuncType, TupleTypes >... >, sizeof...(TupleTypes)> apply_return_array_t
Definition: cpg_types.hpp:1859
constexpr auto reverse(sequence< ms... > mm, sequence< rs... >)
Definition: cpg_types.hpp:4248
enable_if_all_apply_t< apply_return_array_t< FuncType, TupleTypes... >, FuncType, TupleTypes... > array_if_all_apply_t
Definition: cpg_types.hpp:1874
constexpr decltype(auto) unsigned_cast(ArgTypes... args)
Definition: cpg_types.hpp:1209
constexpr decltype(auto) for_stallion_tuple(WorkType &&work, ArgTypes &&... args)
Definition: cpg_types.hpp:4293
std::make_index_sequence<(std::size_t) N > make_index_t
Definition: cpg_types.hpp:910
constexpr auto not_a_number() noexcept
Definition: cpg_types.hpp:228
void truncation_test(S &&s)
Definition: cpg_types.hpp:1171
constexpr auto get_total(sequence< head, tails... >)
Definition: cpg_types.hpp:4230
constexpr auto make_tuple(ArgTypes &&... args) noexcept
Definition: cpg_types.hpp:2704
std::enable_if_t< common_apply_v< FuncType, TupleTypes... >, std::common_type_t< apply_return_t< FuncType, TupleTypes >... > > common_type_if_all_apply_t
Definition: cpg_types.hpp:1882
constexpr auto return_type(FuncType func, Type)
Definition: cpg_types.hpp:858
constexpr auto difference_absolute(arithmetic_c auto a, arithmetic_c auto b) noexcept
Definition: cpg_types.hpp:1018
decltype(hidden::generate_height_row_column_value< T, Heights, Rows, Columns >()) generate_height_row_column_value
Definition: cpg_types.hpp:3928
enable_if_all_apply_t< apply_return_vector_t< FuncType, TupleTypes... >, FuncType, TupleTypes... > vector_if_all_apply_t
Definition: cpg_types.hpp:1878
void display_nontypes(std::basic_ostream< CharType > &os, nontype_container<>) noexcept
Definition: cpg_types.hpp:777
constexpr auto operator+(safe_cast_operation< L > const &a, safe_cast_operation< R > const &b) noexcept
Definition: cpg_types.hpp:1938
auto reverse_array(std::array< Type, N > const &array)
Definition: cpg_types.hpp:4417
decltype(hidden::fn_make_sequence< T, START, END, STEP >(std::integer_sequence< T >{})) make_sequence
Definition: cpg_types.hpp:3359
std::integer_sequence< std::common_type_t< std::remove_cvref_t< decltype(Indices)>... >, Indices... > sequence
Definition: cpg_types.hpp:2665
constexpr decltype(auto) tuple_to_array_recursive(TupleType &&tuple)
Definition: cpg_types.hpp:4398
auto make_vector_of_variants(Types... args)
Definition: cpg_types.hpp:3207
constexpr auto get_index(sequence< head, indices... > index, sequence< ms... > mm)
Definition: cpg_types.hpp:4254
constexpr std::enable_if_t< std::is_same_v< std::remove_reference_t< TargetType >, std::remove_reference_t< _Ty > >, _Ty && > smart_forward(std::remove_reference_t< _Ty > &_Arg) noexcept
Definition: cpg_types.hpp:1237
std::make_index_sequence< sizeof...(Types)> index_for
Definition: cpg_types.hpp:913
constexpr auto operator*(safe_cast_operation< L > const &a, safe_cast_operation< R > const &b) noexcept
Definition: cpg_types.hpp:1990
decltype(hidden::fn_apply(std::declval< FuncType >(), std::declval< TupleType >())) apply_return_t
Definition: cpg_types.hpp:1835
constexpr auto create_tuple_sequence(std::integer_sequence< T, args... > dimensions)
Definition: cpg_types.hpp:4266
constexpr auto make_array(ArgTypes &&... args) noexcept
Definition: cpg_types.hpp:2698
typename hidden::st_signed_type< std::remove_cvref_t< T > >::type make_signed_t
Definition: cpg_types.hpp:1005
Includes subnamespace conversion.
constexpr auto type_max_v
Definition: cpg_types.hpp:217
constexpr auto endl
Definition: cpg_types.hpp:213
constexpr auto endL
Definition: cpg_types.hpp:214
constexpr auto flush
Definition: cpg_types.hpp:211
unsigned long long big_unsigned_t
Definition: cpg_types.hpp:223
constexpr auto clear
Definition: cpg_types.hpp:212
constexpr size_t SelectAll
Definition: cpg_types.hpp:220
constexpr size_t InvalidIndex
Definition: cpg_types.hpp:219
constexpr const bool bDetectOverFlow
Definition: cpg_types.hpp:754
long long big_integer_t
Definition: cpg_types.hpp:222
constexpr decltype(auto) apply(F &&f, T(&&c_array)[N])
typename st_common_type_solver< Types... >::type common_type_t
Definition: tpf_types.hpp:4119
constexpr auto tuple_size_v
Definition: tpf_types.hpp:1913
Type to string name conversions are defined.
Definition: 31-visit.cpp:7
enable_if_all_apply_t< apply_return_tuple_t< FuncType, TupleTypes... >, FuncType, TupleTypes... > tuple_if_all_apply_t
Definition: tpf_types.hpp:5292
std::common_type_t< apply_return_t< FuncType, TupleTypes >... > common_apply_t
Definition: tpf_types.hpp:5260
enable_if_variant_t< VariantType > visit(VisitorType &&visitor, VariantType &&vt)
Definition: 31-visit.cpp:118
remove_cv_ref_t< Type > remove_cvref_t
Definition: tpf_types.hpp:298
enable_if_all_apply_t< apply_return_vector_t< FuncType, TupleTypes... >, FuncType, TupleTypes... > vector_if_all_apply_t
Definition: tpf_types.hpp:5300
enable_if_all_apply_t< apply_return_array_t< FuncType, TupleTypes... >, FuncType, TupleTypes... > array_if_all_apply_t
Definition: tpf_types.hpp:5296
std::string m_char
Definition: cpg_types.hpp:255
std::wstring m_wchar
Definition: cpg_types.hpp:256
std::conditional_t< std::is_same_v< S, common_t >, ContainerTmpl< S, S_tail... >, ContainerTmpl< T, T_tail... > > type
Definition: cpg_types.hpp:1777
std::vector< typename st_common_vector< A, B >::type > type
Definition: cpg_types.hpp:2759
std::vector< std::array< typename st_common_vector< A, B >::type, N > > type
Definition: cpg_types.hpp:2783
std::vector< std::array< typename st_common_vector< A, B >::type, N > > type
Definition: cpg_types.hpp:2801
std::vector< typename st_common_vector< A, B >::type > type
Definition: cpg_types.hpp:2753
std::vector< typename st_common_vector< A, B >::type > type
Definition: cpg_types.hpp:2741
std::vector< std::array< typename st_common_vector< A, B >::type, N > > type
Definition: cpg_types.hpp:2789
std::vector< std::array< typename st_common_vector< A, B >::type, N > > type
Definition: cpg_types.hpp:2795
std::vector< std::array< typename st_common_vector< A, B >::type, N > > type
Definition: cpg_types.hpp:2777
make_sequence< no_t,(no_t) 0, END, 1 > type
Definition: cpg_types.hpp:3656
make_sequence< no_t, START,(no_t) END,(no_t) STEP > type
Definition: cpg_types.hpp:3670
make_sequence< no_t, START,(no_t) END, START< END ?(no_t) 1 :(no_t) -1 > type
Definition: cpg_types.hpp:3663
std::integer_sequence< long long > type
Definition: cpg_types.hpp:3649
typename st_make_unique_types< type_container<>, type_container< Type, Types... > >::type type
Definition: cpg_types.hpp:3133
typename st_make_unique_types< new_left_t, type_container< Second, Tails... > >::type type
Definition: cpg_types.hpp:3160
typename st_make_unique_types< type_container< LeftTypes... >, type_container< First > >::type new_left_t
Definition: cpg_types.hpp:3157
std::conditional_t< is_in_type_container_c< Head, type_container< LeftTypes... > >, type_container< LeftTypes... >, type_container< LeftTypes..., Head > > type
Definition: cpg_types.hpp:3149
typename st_make_unique_types< type_container<>, type_container< Types... > >::type type
Definition: cpg_types.hpp:3142
decltype(fn_pop_back(type_container<>{}, type_container< Type, Types... >{})) type
Definition: cpg_types.hpp:2996
decltype(fn_pop_back(type_container<>{}, type_container< Types... >{})) type
Definition: cpg_types.hpp:3002
std::array< typename st_std_common_array< A, B >::type, N > type
Definition: cpg_types.hpp:3513
std::array< typename st_std_common_array< A, B >::type, N > type
Definition: cpg_types.hpp:3507
std::array< typename st_std_common_array< A, B >::type, N > type
Definition: cpg_types.hpp:3495
static constexpr T Index
Definition: cpg_types.hpp:919
static constexpr T Size
Definition: cpg_types.hpp:920
static constexpr auto end
Definition: cpg_types.hpp:3625
static constexpr auto step
Definition: cpg_types.hpp:3626
static constexpr auto start
Definition: cpg_types.hpp:3619
static constexpr auto last
Definition: cpg_types.hpp:3622
static constexpr auto value
Definition: cpg_types.hpp:3620
static constexpr T column
Definition: cpg_types.hpp:3689
static constexpr T value
Definition: cpg_types.hpp:3690
static constexpr T size
Definition: cpg_types.hpp:3691
static constexpr T row
Definition: cpg_types.hpp:3688