12#ifndef _TPF_STD_EXTENSIONS_HPP
13#define _TPF_STD_EXTENSIONS_HPP
21 #if _MSVC_LANG < 201703L
22 #error This libary requires C++17 Standard (Visual Studio 2017).
27 #if __cplusplus < 201703
28 #error This library requires C++17 Standard (GNU g++ version 8.0 or clang++ version 8.0 above)
34#pragma warning(disable: 4244)
43 template<
typename OperationType,
typename... ArgTypes>
44 auto apply_operation(OperationType&& operation,
const std::tuple<ArgTypes...>& tuple);
46 template<
typename OperationType,
typename T,
size_t Size>
47 auto apply_operation(OperationType&& operation,
const std::array<T, Size>& array);
49 template<
typename OperationType,
typename T,
size_t Size>
52 template<
typename T,
size_t Size1,
size_t Size2,
typename = std::enable_if_t<Size1 != Size2>>
53 auto operator==(
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b);
55 template<
typename T,
size_t Size1,
size_t Size2,
typename = std::enable_if_t<Size1 != Size2>>
56 auto operator!=(
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b);
58 template<
typename T,
typename S,
size_t Size,
59 typename = std::enable_if_t<!std::is_same_v<T, S>>>
60 auto operator == (
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b);
62 template<
typename T,
typename S,
size_t Size,
63 typename = std::enable_if_t<!std::is_same_v<T, S>>>
64 auto operator != (
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b);
66 template<
typename T,
typename S,
size_t Size,
67 typename = std::enable_if_t<!std::is_same_v<T, S>>>
68 auto operator < (
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b);
70 template<
typename T,
typename S,
size_t Size,
71 typename = std::enable_if_t<!std::is_same_v<T, S>>>
72 auto operator <= (
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b);
74 template<
typename T,
typename S,
size_t Size,
75 typename = std::enable_if_t<!std::is_same_v<T, S>>>
76 auto operator > (
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b);
78 template<
typename T,
typename S,
size_t Size,
79 typename = std::enable_if_t<!std::is_same_v<T, S>>>
80 auto operator >= (
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b);
83 template<
typename T,
size_t Size1,
size_t Size2,
typename = std::enable_if_t<Size1 != Size2>>
84 auto operator < (
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b);
86 template<
typename T,
size_t Size1,
size_t Size2,
typename = std::enable_if_t<Size1 != Size2>>
87 auto operator <= (
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b);
89 template<
typename T,
size_t Size1,
size_t Size2,
typename = std::enable_if_t<Size1 != Size2>>
90 auto operator > (
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b);
92 template<
typename T,
size_t Size1,
size_t Size2,
typename = std::enable_if_t<Size1 != Size2>>
93 auto operator >= (
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b);
100 template<
typename... ArgTypes1,
typename... ArgTypes2,
102 typename = std::enable_if_t<!std::is_same_v<common_type, std::tuple<>>>>
103 auto operator+(
const std::tuple<ArgTypes1...>& tuple_a,
const std::tuple<ArgTypes2...>& tuple_b);
105 template<
typename... ArgTypes1,
typename... ArgTypes2,
107 typename = std::enable_if_t<!std::is_same_v<common_type, std::tuple<>>>>
108 auto operator-(
const std::tuple<ArgTypes1...>& tuple_a,
const std::tuple<ArgTypes2...>& tuple_b);
110 template<
typename... ArgTypes1,
typename... ArgTypes2,
112 typename = std::enable_if_t<!std::is_same_v<common_type, std::tuple<>>>>
113 auto operator*(
const std::tuple<ArgTypes1...>& tuple_a,
const std::tuple<ArgTypes2...>& tuple_b);
115 template<
typename... ArgTypes1,
typename... ArgTypes2,
117 typename = std::enable_if_t<!std::is_same_v<common_type, std::tuple<>>>>
118 auto operator/(
const std::tuple<ArgTypes1...>& tuple_a,
const std::tuple<ArgTypes2...>& tuple_b);
120 template<
typename T,
typename S>
126 if constexpr(types::is_addition_valid_v<a_t, b_t>)
136 template<
typename T,
typename S>
142 if constexpr(types::is_subtraction_valid_v<a_t, b_t>)
152 template<
typename T,
typename S>
158 if constexpr(types::is_multiplication_valid_v<a_t, b_t>)
168 template<
typename T,
typename S>
174 if constexpr(types::is_division_valid_v<a_t, b_t>)
186 template<
typename... ArgTypes1,
typename... ArgTypes2,
auto... Indices>
190 return std::tuple{ (std::get<Indices>(tuple_a) + std::get<Indices>(tuple_b))... };
193 template<
typename T,
typename S,
auto Size,
auto... Indices>
197 auto equal_opr = [&array_a, &array_b](
auto indexer)
199 if constexpr(types::is_std_array_v<T> && types::is_std_array_v<S>)
201 return array_a[indexer.Index] == array_b[indexer.Index] ;
203 else if constexpr(!types::is_std_array_v<T> && !types::is_std_array_v<T>)
205 return array_a[indexer.Index] == array_b[indexer.Index];
214 template<
typename T,
typename S,
auto Size,
auto... Indices>
220 auto equal_opr = [&array_a, &array_b](
auto indexer)
222 if constexpr(types::is_std_array_v<T> && types::is_std_array_v<S>)
224 return array_a[indexer.Index] < array_b[indexer.Index] ;
226 else if constexpr(!types::is_std_array_v<T> && !types::is_std_array_v<T>)
228 return (
common_t)array_a[indexer.Index] < (
common_t)array_b[indexer.Index] ;
241 template<
typename T,
typename S,
auto Size,
auto... Indices>
245 auto equal_opr = [&array_a, &array_b](
auto indexer)
247 if constexpr(types::is_std_array_v<T> && types::is_std_array_v<S>)
249 return array_a[indexer.Index] <= array_b[indexer.Index] ;
251 else if constexpr(!types::is_std_array_v<T> && !types::is_std_array_v<T>)
253 return array_a[indexer.Index] <= array_b[indexer.Index];
262 template<
typename... ArgTypes1,
typename... ArgTypes2,
auto... Indices>
266 return std::tuple{ (std::get<Indices>(tuple_a) - std::get<Indices>(tuple_b))... };
269 template<
typename... ArgTypes1,
typename... ArgTypes2,
auto... Indices>
273 return std::tuple{ (std::get<Indices>(tuple_a) * std::get<Indices>(tuple_b))... };
276 template<
typename... ArgTypes1,
typename... ArgTypes2,
auto... Indices>
280 return std::tuple{ (std::get<Indices>(tuple_a) / std::get<Indices>(tuple_b))... };
283 template<
typename T,
typename... ArgTypes,
auto... Indices>
286 return std::tuple{ (scalar + std::get<Indices>(tuple))... };
289 template<
typename T,
typename... ArgTypes,
auto... Indices>
292 return std::tuple{ (std::get<Indices>(tuple) + scalar)... };
295 template<
typename T,
typename... ArgTypes,
auto... Indices>
298 return std::tuple{ (scalar - std::get<Indices>(tuple))... };
301 template<
typename T,
typename... ArgTypes,
auto... Indices>
304 return std::tuple{ (std::get<Indices>(tuple) - scalar)... };
307 template<
typename T,
typename... ArgTypes,
auto... Indices>
310 return std::tuple{ (scalar * std::get<Indices>(tuple))... };
313 template<
typename T,
typename... ArgTypes,
auto... Indices>
316 return std::tuple{ (std::get<Indices>(tuple) * scalar)... };
319 template<
typename T,
typename... ArgTypes,
auto... Indices>
322 return std::tuple{ (scalar / std::get<Indices>(tuple))... };
325 template<
typename T,
typename... ArgTypes,
auto... Indices>
328 return std::tuple{ (std::get<Indices>(tuple) / scalar)... };
331 template<
typename T,
typename S,
size_t Size,
auto...Indices>
335 return std::array{ (array_a[Indices] + array_b[Indices])... };
338 template<
typename T,
typename S,
size_t Size,
auto...Indices>
342 return std::array{ (array_a[Indices] - array_b[Indices])... };
345 template<
typename T,
typename S,
size_t Size,
auto...Indices>
349 return std::array{ (array_a[Indices] * array_b[Indices])... };
352 template<
typename T,
typename S,
size_t Size,
auto...Indices>
356 return std::array{ (array_a[Indices] / array_b[Indices])... };
359 template<
typename T,
typename S,
size_t Size,
auto...Indices>
363 return std::array{ (scalar + array[Indices])... };
366 template<
typename T,
typename S,
size_t Size,
auto...Indices>
370 return std::array{ (array[Indices] + scalar)... };
373 template<
typename T,
typename S,
size_t Size,
auto...Indices>
377 return std::array{ (scalar - array[Indices])... };
380 template<
typename T,
typename S,
size_t Size,
auto...Indices>
384 return std::array{ (array[Indices] - scalar)... };
387 template<
typename T,
typename S,
size_t Size,
auto...Indices>
391 return std::array{ (scalar * array[Indices])... };
394 template<
typename T,
typename S,
size_t Size,
auto...Indices>
398 return std::array{ (array[Indices] * scalar)... };
401 template<
typename T,
typename S,
size_t Size,
auto...Indices>
405 return std::array{ (scalar / array[Indices])... };
408 template<
typename T,
typename S,
size_t Size,
auto...Indices>
412 return std::array{ (array[Indices] / scalar)... };
416 template<
typename OperationType,
typename... ArgTypes,
auto... Indices>
420 auto apply_opr = [&operation, &tuple](
auto indexer)
422 using ele_t = std::tuple_element_t<indexer.Index, std::tuple<ArgTypes...>>;
424 if constexpr(types::is_tuple_v<ele_t>)
430 return operation(std::get<indexer.Index>(tuple));
437 template<
typename OperationType,
typename T,
size_t Size,
auto... Indices>
441 auto apply_opr = [&operation, &array](
auto indexer)
443 using ele_t =
decltype(array[indexer.Index]);
445 if constexpr(types::is_std_array_v<ele_t>)
451 return operation(array[indexer.Index]);
458 template<
typename OperationType,
typename T,
size_t Size,
auto... Indices>
462 auto workhorse = [&operation, &array](
auto indexer)
464 using ele_t =
decltype(array[indexer.Index]);
465 if constexpr(types::is_std_array_v<ele_t>)
471 array[indexer.Index] = operation(array[indexer.Index]);
475 types::drive_workhorse<Size>(workhorse);
482 template<
typename... ArgTypes1,
typename... ArgTypes2,
typename common_type,
typename>
483 auto operator+(
const std::tuple<ArgTypes1...>& tuple_a,
const std::tuple<ArgTypes2...>& tuple_b)
485 constexpr auto Size =
sizeof...(ArgTypes1);
489 template<
typename... ArgTypes1,
typename... ArgTypes2,
typename common_type,
typename>
490 auto operator-(
const std::tuple<ArgTypes1...>& tuple_a,
const std::tuple<ArgTypes2...>& tuple_b)
492 constexpr auto Size =
sizeof...(ArgTypes1);
496 template<
typename... ArgTypes1,
typename... ArgTypes2,
typename common_type,
typename>
497 auto operator*(
const std::tuple<ArgTypes1...>& tuple_a,
const std::tuple<ArgTypes2...>& tuple_b)
499 constexpr auto Size =
sizeof...(ArgTypes1);
503 template<
typename... ArgTypes1,
typename... ArgTypes2,
typename common_type,
typename>
504 auto operator/(
const std::tuple<ArgTypes1...>& tuple_a,
const std::tuple<ArgTypes2...>& tuple_b)
506 constexpr auto Size =
sizeof...(ArgTypes1);
511 template<
typename T,
typename... ArgTypes>
512 auto operator+(
const T& scalar,
const std::tuple<ArgTypes...>& tuple)
514 constexpr auto Size =
sizeof...(ArgTypes);
518 template<
typename T,
typename... ArgTypes>
519 auto operator+(
const std::tuple<ArgTypes...>& tuple,
const T& scalar)
521 constexpr auto Size =
sizeof...(ArgTypes);
525 template<
typename T,
typename... ArgTypes>
526 auto operator-(
const T& scalar,
const std::tuple<ArgTypes...>& tuple)
528 constexpr auto Size =
sizeof...(ArgTypes);
532 template<
typename T,
typename... ArgTypes>
533 auto operator-(
const std::tuple<ArgTypes...>& tuple,
const T& scalar)
535 constexpr auto Size =
sizeof...(ArgTypes);
539 template<
typename T,
typename... ArgTypes>
540 auto operator*(
const T& scalar,
const std::tuple<ArgTypes...>& tuple)
542 constexpr auto Size =
sizeof...(ArgTypes);
546 template<
typename T,
typename... ArgTypes>
547 auto operator*(
const std::tuple<ArgTypes...>& tuple,
const T& scalar)
549 constexpr auto Size =
sizeof...(ArgTypes);
553 template<
typename T,
typename... ArgTypes>
554 auto operator/(
const T& scalar,
const std::tuple<ArgTypes...>& tuple)
556 constexpr auto Size =
sizeof...(ArgTypes);
560 template<
typename T,
typename... ArgTypes>
561 auto operator/(
const std::tuple<ArgTypes...>& tuple,
const T& scalar)
563 constexpr auto Size =
sizeof...(ArgTypes);
568 template<
typename OperationType,
typename... ArgTypes>
571 constexpr auto Size =
sizeof...(ArgTypes);
576 template<
typename OperationType,
typename... ArgTypes>
579 constexpr auto Size =
tuple_size_v<std::tuple<ArgTypes...>>;
581 auto workhorse = [&operation, &tuple](
auto indexer)
583 using ele_t = std::tuple_element_t<indexer.Index, std::tuple<ArgTypes...>>;
585 if constexpr(types::is_tuple_v<ele_t>)
592 operation(std::get<indexer.Index>(tuple));
596 types::drive_workhorse<Size>(workhorse);
601 template<
typename T,
size_t Size1,
size_t Size2,
typename>
602 auto operator==(
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b)
607 template<
typename T,
size_t Size1,
size_t Size2,
typename>
608 auto operator!=(
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b)
613 template<
typename T,
size_t Size1,
size_t Size2,
typename>
614 auto operator < (
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b)
619 template<
typename T,
size_t Size1,
size_t Size2,
typename>
620 auto operator <= (
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b)
625 template<
typename T,
size_t Size1,
size_t Size2,
typename>
626 auto operator > (
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b)
631 template<
typename T,
size_t Size1,
size_t Size2,
typename>
632 auto operator >= (
const std::array<T, Size1>& array_a,
const std::array<T, Size2>& array_b)
637 template<
typename T,
typename S,
size_t Size,
typename>
638 auto operator==(
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b)
643 template<
typename T,
typename S,
size_t Size,
typename>
644 auto operator!=(
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b)
649 template<
typename T,
typename S,
size_t Size,
typename>
650 auto operator < (
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b)
655 template<
typename T,
typename S,
size_t Size,
typename>
656 auto operator <= (
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b)
661 template<
typename T,
typename S,
size_t Size,
typename>
662 auto operator > (
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b)
667 template<
typename T,
typename S,
size_t Size,
typename>
668 auto operator >= (
const std::array<T, Size>& array_a,
const std::array<S, Size>& array_b)
673 template<
typename T,
typename S,
size_t Size>
675 const std::array<S, Size>& array_b)
680 template<
typename T,
typename S,
size_t Size>
682 const std::array<S, Size>& array_b)
687 template<
typename T,
typename S,
size_t Size>
689 const std::array<S, Size>& array_b)
694 template<
typename T,
typename S,
size_t Size>
696 const std::array<S, Size>& array_b)
702 template<
typename T,
typename S,
size_t Size>
703 auto operator+(
const T& scalar,
const std::array<S, Size>& array)
708 template<
typename T,
typename S,
size_t Size>
709 auto operator+(
const std::array<S, Size>& array,
const T& scalar)
714 template<
typename T,
typename S,
size_t Size>
715 auto operator-(
const T& scalar,
const std::array<S, Size>& array)
720 template<
typename T,
typename S,
size_t Size>
721 auto operator-(
const std::array<S, Size>& array,
const T& scalar)
726 template<
typename T,
typename S,
size_t Size>
727 auto operator*(
const T& scalar,
const std::array<S, Size>& array)
732 template<
typename T,
typename S,
size_t Size>
733 auto operator*(
const std::array<S, Size>& array,
const T& scalar)
738 template<
typename T,
typename S,
size_t Size>
739 auto operator/(
const T& scalar,
const std::array<S, Size>& array)
744 template<
typename T,
typename S,
size_t Size>
745 auto operator/(
const std::array<S, Size>& array,
const T& scalar)
750 template<
typename OperationType,
typename T,
size_t Size>
756 template<
typename OperationType,
typename T,
size_t Size>
762 template<
typename... Elements,
typename commom_element_type
766 commom_element_type
sum{};
768 constexpr auto Size =
sizeof...(Elements);
770 types::for_workhorse<Size>(
771 [&
sum, &tuple](
auto indexer)
780 template<
typename... Elements,
typename commom_element_type
785 constexpr auto Size =
sizeof...(Elements);
790 template<
typename... Elements,
typename commom_element_type
796 constexpr auto Size =
sizeof...(Elements);
798 double denominator = 1.0 / Size;
801 types::for_workhorse<Size>(
802 [&denominator, &deviation, &mean, &tuple](
auto indexer)
811 return std::sqrt(deviation);
818 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list>, std::variant<EleTypes...>>
820 const std::variant<EleTypes...>& variant_b)
822 constexpr auto Size =
sizeof...(EleTypes);
824 std::variant<EleTypes...> result;
828 types::for_workhorse<Size>([&result, &variant_a, &variant_b](
auto first)
830 constexpr auto Size =
sizeof...(EleTypes);
832 if(
auto a = std::get_if<first.Index>(&variant_a))
834 types::for_workhorse<Size>([&](
auto second)
836 if(
auto b = std::get_if<second.Index>(&variant_b))
856 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list>, std::variant<EleTypes...>>
858 const std::variant<EleTypes...>& variant_b)
860 constexpr auto Size =
sizeof...(EleTypes);
862 std::variant<EleTypes...> result;
866 types::for_workhorse<Size>([&result, &variant_a, &variant_b](
auto first)
868 constexpr auto Size =
sizeof...(EleTypes);
870 if(
auto a = std::get_if<first.Index>(&variant_a))
872 types::for_workhorse<Size>([&](
auto second)
874 if(
auto b = std::get_if<second.Index>(&variant_b))
894 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list>, std::variant<EleTypes...>>
896 const std::variant<EleTypes...>& variant_b)
898 constexpr auto Size =
sizeof...(EleTypes);
900 std::variant<EleTypes...> result;
904 types::for_workhorse<Size>([&result, &variant_a, &variant_b](
auto first)
906 constexpr auto Size =
sizeof...(EleTypes);
908 if(
auto a = std::get_if<first.Index>(&variant_a))
910 types::for_workhorse<Size>([&](
auto second)
912 if(
auto b = std::get_if<second.Index>(&variant_b))
932 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list>, std::variant<EleTypes...>>
934 const std::variant<EleTypes...>& variant_b)
936 constexpr auto Size =
sizeof...(EleTypes);
938 std::variant<EleTypes...> result;
942 types::for_workhorse<Size>([&result, &variant_a, &variant_b](
auto first)
944 constexpr auto Size =
sizeof...(EleTypes);
946 if(
auto a = std::get_if<first.Index>(&variant_a))
948 types::for_workhorse<Size>([&](
auto second)
950 if(
auto b = std::get_if<second.Index>(&variant_b))
952 result = fail_safe_operation(*a, *b);
968 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
969 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list> &&
970 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
971 operator+(
const T& v,
const std::variant<EleTypes...>& variant)
973 constexpr auto Size =
sizeof...(EleTypes);
975 std::variant<EleTypes...> result;
979 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
981 if(
auto a = std::get_if<indexer.Index>(&variant))
997 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
998 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list> &&
999 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1000 operator+(
const std::variant<EleTypes...>& variant,
const T& v)
1002 constexpr auto Size =
sizeof...(EleTypes);
1004 std::variant<EleTypes...> result;
1008 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1010 if(
auto a = std::get_if<indexer.Index>(&variant))
1026 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1027 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list> &&
1028 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1029 operator-(
const T& v,
const std::variant<EleTypes...>& variant)
1031 constexpr auto Size =
sizeof...(EleTypes);
1033 std::variant<EleTypes...> result;
1037 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1039 if(
auto a = std::get_if<indexer.Index>(&variant))
1055 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1056 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list> &&
1057 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1058 operator-(
const std::variant<EleTypes...>& variant,
const T& v)
1060 constexpr auto Size =
sizeof...(EleTypes);
1062 std::variant<EleTypes...> result;
1066 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1068 if(
auto a = std::get_if<indexer.Index>(&variant))
1084 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1085 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list> &&
1086 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1087 operator*(
const T& v,
const std::variant<EleTypes...>& variant)
1089 constexpr auto Size =
sizeof...(EleTypes);
1091 std::variant<EleTypes...> result;
1095 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1097 if(
auto a = std::get_if<indexer.Index>(&variant))
1099 result = fail_safe_mulitplication(v, *a);
1113 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1114 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list> &&
1115 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1116 operator*(
const std::variant<EleTypes...>& variant,
const T& v)
1118 constexpr auto Size =
sizeof...(EleTypes);
1120 std::variant<EleTypes...> result;
1124 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1126 if(
auto a = std::get_if<indexer.Index>(&variant))
1142 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1143 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list> &&
1144 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1145 operator/(
const T& v,
const std::variant<EleTypes...>& variant)
1147 constexpr auto Size =
sizeof...(EleTypes);
1149 std::variant<EleTypes...> result;
1153 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1155 if(
auto a = std::get_if<indexer.Index>(&variant))
1171 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1172 std::enable_if_t<types::is_type_in_list_v<types::no_throw_t, list> &&
1173 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1174 operator/(
const std::variant<EleTypes...>& variant,
const T& v)
1176 constexpr auto Size =
sizeof...(EleTypes);
1178 std::variant<EleTypes...> result;
1182 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1184 if(
auto a = std::get_if<indexer.Index>(&variant))
1204 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list>, std::variant<EleTypes...>>
1206 const std::variant<EleTypes...>& variant_b)
1208 constexpr auto Size =
sizeof...(EleTypes);
1210 std::variant<EleTypes...> result;
1214 types::for_workhorse<Size>([&result, &variant_a, &variant_b](
auto first)
1216 constexpr auto Size =
sizeof...(EleTypes);
1218 if(
auto a = std::get_if<first.Index>(&variant_a))
1220 types::for_workhorse<Size>([&](
auto second)
1222 if(
auto b = std::get_if<second.Index>(&variant_b))
1227 if constexpr(types::is_addition_valid_v<ele_a_t, ele_b_t>)
1229 result = (*a) + (*b);
1237 throw std::bad_variant_access{};
1253 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list>, std::variant<EleTypes...>>
1255 const std::variant<EleTypes...>& variant_b)
1257 constexpr auto Size =
sizeof...(EleTypes);
1259 std::variant<EleTypes...> result;
1263 types::for_workhorse<Size>([&result, &variant_a, &variant_b](
auto first)
1265 constexpr auto Size =
sizeof...(EleTypes);
1267 if(
auto a = std::get_if<first.Index>(&variant_a))
1269 types::for_workhorse<Size>([&](
auto second)
1271 if(
auto b = std::get_if<second.Index>(&variant_b))
1276 if constexpr(types::is_subtraction_valid_v<ele_a_t, ele_b_t>)
1278 result = (*a) - (*b);
1286 throw std::bad_variant_access{};
1302 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list>, std::variant<EleTypes...>>
1304 const std::variant<EleTypes...>& variant_b)
1306 constexpr auto Size =
sizeof...(EleTypes);
1308 std::variant<EleTypes...> result;
1312 types::for_workhorse<Size>([&result, &variant_a, &variant_b](
auto first)
1314 constexpr auto Size =
sizeof...(EleTypes);
1316 if(
auto a = std::get_if<first.Index>(&variant_a))
1318 types::for_workhorse<Size>([&](
auto second)
1320 if(
auto b = std::get_if<second.Index>(&variant_b))
1325 if constexpr(types::is_multiplication_valid_v<ele_a_t, ele_b_t>)
1327 result = (*a) * (*b);
1335 throw std::bad_variant_access{};
1351 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list>, std::variant<EleTypes...>>
1353 const std::variant<EleTypes...>& variant_b)
1355 constexpr auto Size =
sizeof...(EleTypes);
1357 std::variant<EleTypes...> result;
1361 types::for_workhorse<Size>([&result, &variant_a, &variant_b](
auto first)
1363 constexpr auto Size =
sizeof...(EleTypes);
1365 if(
auto a = std::get_if<first.Index>(&variant_a))
1367 types::for_workhorse<Size>([&](
auto second)
1369 if(
auto b = std::get_if<second.Index>(&variant_b))
1374 if constexpr(types::is_division_valid_v<ele_a_t, ele_b_t>)
1376 result = (*a) / (*b);
1384 throw std::bad_variant_access{};
1399 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1400 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list> &&
1401 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1402 operator+(
const T& v,
const std::variant<EleTypes...>& variant)
1404 constexpr auto Size =
sizeof...(EleTypes);
1406 std::variant<EleTypes...> result;
1410 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1412 if(
auto a = std::get_if<indexer.Index>(&variant))
1416 if constexpr(types::is_addition_valid_v<T, ele_a_t>)
1426 throw std::bad_variant_access{};
1438 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1439 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list> &&
1440 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1441 operator+(
const std::variant<EleTypes...>& variant,
const T& v)
1443 constexpr auto Size =
sizeof...(EleTypes);
1445 std::variant<EleTypes...> result;
1449 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1451 if(
auto a = std::get_if<indexer.Index>(&variant))
1455 if constexpr(types::is_addition_valid_v<ele_a_t, T>)
1463 throw std::bad_variant_access{};
1475 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1476 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list> &&
1477 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1478 operator-(
const T& v,
const std::variant<EleTypes...>& variant)
1480 constexpr auto Size =
sizeof...(EleTypes);
1482 std::variant<EleTypes...> result;
1486 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1488 if(
auto a = std::get_if<indexer.Index>(&variant))
1492 if constexpr(types::is_subtraction_valid_v<T, ele_a_t>)
1502 throw std::bad_variant_access{};
1514 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1515 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list> &&
1516 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1517 operator-(
const std::variant<EleTypes...>& variant,
const T& v)
1519 constexpr auto Size =
sizeof...(EleTypes);
1521 std::variant<EleTypes...> result;
1525 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1527 if(
auto a = std::get_if<indexer.Index>(&variant))
1531 if constexpr(types::is_subtraction_valid_v<ele_a_t, T>)
1541 throw std::bad_variant_access{};
1553 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1554 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list> &&
1555 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1556 operator*(
const T& v,
const std::variant<EleTypes...>& variant)
1558 constexpr auto Size =
sizeof...(EleTypes);
1560 std::variant<EleTypes...> result;
1564 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1566 if(
auto a = std::get_if<indexer.Index>(&variant))
1570 if constexpr(types::is_multiplication_valid_v<T, ele_a_t>)
1580 throw std::bad_variant_access{};
1592 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1593 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list> &&
1594 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1595 operator*(
const std::variant<EleTypes...>& variant,
const T& v)
1597 constexpr auto Size =
sizeof...(EleTypes);
1599 std::variant<EleTypes...> result;
1603 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1605 if(
auto a = std::get_if<indexer.Index>(&variant))
1609 if constexpr(types::is_multiplication_valid_v<ele_a_t, T>)
1619 throw std::bad_variant_access{};
1631 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1632 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list> &&
1633 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1634 operator/(
const T& v,
const std::variant<EleTypes...>& variant)
1636 constexpr auto Size =
sizeof...(EleTypes);
1638 std::variant<EleTypes...> result;
1642 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1644 if(
auto a = std::get_if<indexer.Index>(&variant))
1648 if constexpr(types::is_division_valid_v<T, ele_a_t>)
1658 throw std::bad_variant_access{};
1670 template<
typename T,
typename ...EleTypes,
typename list =
types::type_list_t<EleTypes...>>
1671 std::enable_if_t<!types::is_type_in_list_v<types::no_throw_t, list> &&
1672 types::is_type_in_list_v<T, list>, std::variant<EleTypes...>>
1673 operator/(
const std::variant<EleTypes...>& variant,
const T& v)
1675 constexpr auto Size =
sizeof...(EleTypes);
1677 std::variant<EleTypes...> result;
1681 types::for_workhorse<Size>([&result, &v, &variant](
auto indexer)
1683 if(
auto a = std::get_if<indexer.Index>(&variant))
1687 if constexpr(types::is_division_valid_v<ele_a_t, T>)
1697 throw std::bad_variant_access{};
1709 template<auto N1, auto D1, auto N2, auto D2>
1710 constexpr auto operator*(std::ratio<N1, D1>, std::ratio<N2, D2>)
1718 constexpr std::ratio<N1, D2> aa;
1719 constexpr std::ratio<N2, D1> bb;
1721 return std::ratio<aa.num * bb.num, aa.den * bb.den>{};
1724 template<auto N1, auto D1, auto N2, auto D2>
1725 constexpr auto operator/(std::ratio<N1, D1> a, std::ratio<N2, D2>)
1727 constexpr std::ratio<D2, N2> bb;
1732 template<auto N1, auto D1, auto N2, auto D2>
1733 constexpr auto operator+(std::ratio<N1, D1>, std::ratio<N2, D2>)
1742 constexpr auto g =
std::gcd(D1, D2);
1743 constexpr auto l =
std::lcm(D1, D2);
1745 constexpr auto d2_g = D2 / g;
1746 constexpr auto d1_g = D1 / g;
1748 return std::ratio<d2_g * N1 + d1_g * N2, l>{};
1751 template<auto N1, auto D1, auto N2, auto D2>
1752 constexpr auto operator-(std::ratio<N1, D1>, std::ratio<N2, D2>)
1761 constexpr auto g =
std::gcd(D1, D2);
1762 constexpr auto l =
std::lcm(D1, D2);
1764 constexpr auto d2_g = D2 / g;
1765 constexpr auto d1_g = D1 / g;
1767 return std::ratio<d2_g * N1 - d1_g * N2, l>{};
1772 #pragma warning(pop)
return_t sum(int a, int b)
std::common_type_t< S, T > common_t
auto apply_operation_inplace(OperationType &&operation, std::array< T, Size > &array, types::typed_sequence_t< Indices... >)
auto tuple_addition(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b, types::typed_sequence_t< Indices... >)
auto tuple_division(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b, types::typed_sequence_t< Indices... >)
auto array_less(const std::array< T, Size > &array_a, const std::array< S, Size > &array_b, types::typed_sequence_t< Indices... >)
auto array_equality(const std::array< T, Size > &array_a, const std::array< S, Size > &array_b, types::typed_sequence_t< Indices... >)
auto array_division(const std::array< T, Size > &array_a, const std::array< S, Size > &array_b, types::typed_sequence_t< Indices... >)
auto apply_operation(OperationType &&operation, const std::tuple< ArgTypes... > &tuple, types::typed_sequence_t< Indices... >)
auto array_multiplication(const std::array< T, Size > &array_a, const std::array< S, Size > &array_b, types::typed_sequence_t< Indices... >)
auto tuple_multiplication(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b, types::typed_sequence_t< Indices... >)
auto array_less_equal(const std::array< T, Size > &array_a, const std::array< S, Size > &array_b, types::typed_sequence_t< Indices... >)
auto tuple_subtraction(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b, types::typed_sequence_t< Indices... >)
auto array_subtraction(const std::array< T, Size > &array_a, const std::array< S, Size > &array_b, types::typed_sequence_t< Indices... >)
auto array_addition(const std::array< T, Size > &array_a, const std::array< S, Size > &array_b, types::typed_sequence_t< Indices... >)
auto operator!=(const std::array< T, Size1 > &array_a, const std::array< T, Size2 > &array_b)
auto operator==(const std::array< T, Size1 > &array_a, const std::array< T, Size2 > &array_b)
double standard_deviation(const std::tuple< Elements... > &tuple)
auto fail_safe_subtraction(T &&a, T &&b)
auto fail_safe_division(T &&a, S &&b)
auto fail_safe_addition(T &&a, T &&b)
auto operator<=(const std::array< T, Size > &array_a, const std::array< S, Size > &array_b)
auto apply_operation(OperationType &&operation, const std::tuple< ArgTypes... > &tuple)
auto operator>=(const std::array< T, Size > &array_a, const std::array< S, Size > &array_b)
void apply_operation_inplace(OperationType &&operation, std::array< T, Size > &array)
auto sum_of_elements(const std::tuple< Elements... > &tuple)
auto operator-(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b)
auto fail_safe_multiplication(T &&a, T &&b)
double mean_of_elements(const std::tuple< Elements... > &tuple)
auto operator+(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b)
auto operator>(const std::array< T, Size > &array_a, const std::array< S, Size > &array_b)
auto operator/(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b)
auto operator*(const std::tuple< ArgTypes1... > &tuple_a, const std::tuple< ArgTypes2... > &tuple_b)
auto operator<(const std::array< T, Size > &array_a, const std::array< S, Size > &array_b)
constexpr decltype(auto) get(T(&c_array)[N]) noexcept
enable_if_in_list_t< Type, integral_list_t > lcm(Type a, Type b)
enable_if_in_list_t< Type, integral_list_t > gcd(Type a, Type b)
ContainerType< EleType, Types... > difference(const ContainerType< EleType, Types... > &left, const ContainerType< EleType, Types... > &right)
constexpr auto tuple_size_v
Type to string name conversions are defined.
std::enable_if_t< tuple_common_type_v< T, S >, tuple_common_type_t< T, S > > tuple_operation_valid_t
std::make_integer_sequence< remove_cvref_t< decltype(Size)>, Size > make_typed_sequence_t
result_type signed_common_t
std::integer_sequence< std::common_type_t< remove_cvref_t< decltype(Indices)>... >, Indices... > typed_sequence_t
hidden::tuple_common_element_t< remove_cvref_t< TupleType > > tuple_common_element_t
remove_cv_ref_t< Type > remove_cvref_t
This type is used to test validity of a type.
This type is used to manipulate type list.
Type functions are implemented.