C++ Library Extensions 2022.12.09
To help learn modern C++ programming
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages Concepts
cpg_std_array_tuple_operations.hpp
Go to the documentation of this file.
1/*
2 Author: Thomas Kim
3 First Edit: Dec. 03, 2021
4 Second Edit: Dec. 09, 2021 - safe binary operation
5*/
6
7#ifndef _CGP_STD_ARRAY_TUPLE_OPERATIONS_HPP
8#define _CGP_STD_ARRAY_TUPLE_OPERATIONS_HPP
9
10#ifndef NOMINMAX
11#define NOMINMAX
12#endif
13
16
17namespace std::inline stl_extensions
18{
19 namespace cgt = cpg::types;
20
21 template<cgt::numerical_c H, cgt::numerical_c... Ts>
22 constexpr decltype(auto) tuple_to_array(std::tuple<H, Ts...> const& tuple) noexcept
23 {
24 using element_t = cgt::common_signed_t<H, Ts...>;
25
26 return cgt::for_stallion<sizeof...(Ts) + 1>
27 ([&]<auto... i>(cgt::sequence<i...>)
28 {
29 return std::array{ static_cast<element_t>(std::get<i>(tuple)) ... };
30 });
31 }
32
33 template<cgt::tuple_flat_c H, cgt::tuple_flat_c... Ts>
34 requires (!cgt::all_same_flat_c<H, Ts...>) &&
35 (std::tuple_size_v<H> == ... == std::tuple_size_v<Ts>)
36 constexpr decltype(auto) tuple_to_array(std::tuple<H, Ts...> const& tuple) noexcept
37 {
38 using tt = decltype(signed_tuple_operation(H{}, Ts{}...));
39
40 return cgt::for_stallion<sizeof...(Ts)+1>
41 ([&]<auto... i>(cgt::sequence<i...>)
42 {
43 return std::array{ tuple_to_array(static_cast<tt>(std::get<i>(tuple)))... };
44 });
45 }
46
47 template<cgt::tuple_flat_c H, cgt::tuple_flat_c... Ts>
48 requires cgt::all_same_flat_c<H, Ts...>
49 constexpr decltype(auto) tuple_to_array(std::tuple<H, Ts...> const& tuple) noexcept
50 {
51 return cgt::for_stallion<sizeof...(Ts)+1>
52 ([&]<auto... i>(cgt::sequence<i...>)
53 {
54 return std::array{ tuple_to_array(std::get<i>(tuple))... };
55 });
56 }
57
58 template<cgt::numerical_c E, std::size_t N>
59 constexpr decltype(auto) array_to_tuple(std::array<E, N> const& array) noexcept
60 {
61 return cgt::for_stallion<N>
62 ([&]<auto... i>(cgt::sequence<i...>)
63 {
64 return std::tuple{ std::get<i>(array)... };
65 });
66 }
67
68 template<cgt::std_array_flat_c E, std::size_t N>
69 constexpr decltype(auto) array_to_tuple(std::array<E, N> const& array) noexcept
70 {
71 return cgt::for_stallion<N>
72 ([&]<auto... i>(cgt::sequence<i...>)
73 {
74 return std::tuple{ array_to_tuple( std::get<i>(array) )... };
75 });
76 }
77
79 template<cgt::numerical_c E, std::size_t N, cgt::numerical_c H, cgt::numerical_c... Ts>
80 requires (N == sizeof...(Ts) + 1)
81 constexpr decltype(auto) operator+
82 (std::array<E, N> const& A, std::tuple<H, Ts...> const& T) noexcept(!cpg::bDetectOverFlow)
83 {
84 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
85 {
86 if constexpr(cgt::all_same_c<H, Ts...>)
87 return std::array{ cgt::sbo(std::get<i>(A)) + cgt::sbo(std::get<i>(T)) ... };
88 else
89 return std::tuple{ cgt::sbo(std::get<i>(A)) + cgt::sbo(std::get<i>(T)) ... };
90 });
91 }
92
93 template<cgt::numerical_c E, std::size_t N, cgt::numerical_c H, cgt::numerical_c... Ts>
94 requires (N == sizeof...(Ts) + 1)
95 constexpr decltype(auto) operator+
96 (std::tuple<H, Ts...> const& T, std::array<E, N> const& A) noexcept(!cpg::bDetectOverFlow)
97 {
98 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
99 {
100 if constexpr(cgt::all_same_c<H, Ts...>)
101 return std::array{ cgt::sbo(std::get<i>(A)) + cgt::sbo(std::get<i>(T)) ... };
102 else
103 return std::tuple{ cgt::sbo(std::get<i>(A)) + cgt::sbo(std::get<i>(T)) ... };
104 });
105 }
106
107 template<typename E, std::size_t N, typename H, typename... Ts>
108 requires (N == sizeof...(Ts) + 1) &&
109 ( !(cgt::numerical_c<E> && (cgt::numerical_c<H> && ... && cgt::numerical_c<Ts>)) )
110 constexpr decltype(auto) operator+
111 (std::array<E, N> const& A, std::tuple<H, Ts...> const& T) noexcept(!cpg::bDetectOverFlow)
112 {
113 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
114 {
115 if constexpr(cgt::all_same_c<H, Ts...>)
116 return std::array{ std::get<i>(A) + std::get<i>(T) ... };
117 else
118 return std::tuple{ std::get<i>(A) + std::get<i>(T) ... };
119 });
120 }
121
122 template<typename E, std::size_t N, typename H, typename... Ts>
123 requires (N == sizeof...(Ts) + 1) &&
124 ( !( cgt::numerical_c<E> && (cgt::numerical_c<H> && ... && cgt::numerical_c<Ts>)) )
125 constexpr decltype(auto) operator+
126 (std::tuple<H, Ts...> const& T, std::array<E, N> const& A) noexcept(!cpg::bDetectOverFlow)
127 {
128 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
129 {
130 if constexpr(cgt::all_same_c<H, Ts...>)
131 return std::array{ std::get<i>(T) + std::get<i>(A) ... };
132 else
133 return std::tuple{ std::get<i>(T) + std::get<i>(A) ... };
134 });
135 }
136
138
139 template<cgt::numerical_c E, std::size_t N, cgt::numerical_c H, cgt::numerical_c... Ts>
140 requires (N == sizeof...(Ts) + 1)
141 constexpr decltype(auto) operator-
142 (std::array<E, N> const& A, std::tuple<H, Ts...> const& T) noexcept(!cpg::bDetectOverFlow)
143 {
144 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
145 {
146 if constexpr(cgt::all_same_c<H, Ts...>)
147 return std::array{ cgt::sbo(std::get<i>(A)) - cgt::sbo(std::get<i>(T)) ... };
148 else
149 return std::tuple{ cgt::sbo(std::get<i>(A)) - cgt::sbo(std::get<i>(T)) ... };
150 });
151 }
152
153 template<cgt::numerical_c E, std::size_t N, cgt::numerical_c H, cgt::numerical_c... Ts>
154 requires (N == sizeof...(Ts) + 1)
155 constexpr decltype(auto) operator-
156 (std::tuple<H, Ts...> const& T, std::array<E, N> const& A) noexcept(!cpg::bDetectOverFlow)
157 {
158 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
159 {
160 if constexpr(cgt::all_same_c<H, Ts...>)
161 return std::array{ cgt::sbo(std::get<i>(T)) - cgt::sbo(std::get<i>(A)) ... };
162 else
163 return std::tuple{ cgt::sbo(std::get<i>(T)) - cgt::sbo(std::get<i>(A)) ... };
164 });
165 }
166
167 template<typename E, std::size_t N, typename H, typename... Ts>
168 requires (N == sizeof...(Ts) + 1) &&
169 ( !(cgt::numerical_c<E> && (cgt::numerical_c<H> && ... && cgt::numerical_c<Ts>)) )
170 constexpr decltype(auto) operator-
171 (std::array<E, N> const& A, std::tuple<H, Ts...> const& T) noexcept(!cpg::bDetectOverFlow)
172 {
173 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
174 {
175 if constexpr(cgt::all_same_c<H, Ts...>)
176 return std::array{ std::get<i>(A) - std::get<i>(T) ... };
177 else
178 return std::tuple{ std::get<i>(A) - std::get<i>(T) ... };
179 });
180 }
181
182 template<typename E, std::size_t N, typename H, typename... Ts>
183 requires (N == sizeof...(Ts) + 1) &&
184 ( !( cgt::numerical_c<E> && (cgt::numerical_c<H> && ... && cgt::numerical_c<Ts>)) )
185 constexpr decltype(auto) operator-
186 (std::tuple<H, Ts...> const& T, std::array<E, N> const& A) noexcept(!cpg::bDetectOverFlow)
187 {
188 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
189 {
190 if constexpr(cgt::all_same_c<H, Ts...>)
191 return std::array{ std::get<i>(T) - std::get<i>(A) ... };
192 else
193 return std::tuple{ std::get<i>(T) - std::get<i>(A) ... };
194 });
195 }
196
198
199 template<cgt::numerical_c E, std::size_t N, cgt::numerical_c H, cgt::numerical_c... Ts>
200 requires (N == sizeof...(Ts) + 1)
201 constexpr decltype(auto) operator*
202 (std::array<E, N> const& A, std::tuple<H, Ts...> const& T) noexcept(!cpg::bDetectOverFlow)
203 {
204 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
205 {
206 if constexpr(cgt::all_same_c<H, Ts...>)
207 return std::array{ cgt::sbo(std::get<i>(A)) * cgt::sbo(std::get<i>(T)) ... };
208 else
209 return std::tuple{ cgt::sbo(std::get<i>(A)) * cgt::sbo(std::get<i>(T)) ... };
210 });
211 }
212
213 template<cgt::numerical_c E, std::size_t N, cgt::numerical_c H, cgt::numerical_c... Ts>
214 requires (N == sizeof...(Ts) + 1)
215 constexpr decltype(auto) operator*
216 (std::tuple<H, Ts...> const& T, std::array<E, N> const& A) noexcept(!cpg::bDetectOverFlow)
217 {
218 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
219 {
220 if constexpr(cgt::all_same_c<H, Ts...>)
221 return std::array{ cgt::sbo(std::get<i>(T)) * cgt::sbo(std::get<i>(A)) ... };
222 else
223 return std::tuple{ cgt::sbo(std::get<i>(T)) * cgt::sbo(std::get<i>(A)) ... };
224 });
225 }
226
227 template<typename E, std::size_t N, typename H, typename... Ts>
228 requires (N == sizeof...(Ts) + 1) &&
229 ( !(cgt::numerical_c<E> && (cgt::numerical_c<H> && ... && cgt::numerical_c<Ts>)) )
230 constexpr decltype(auto) operator*
231 (std::array<E, N> const& A, std::tuple<H, Ts...> const& T) noexcept(!cpg::bDetectOverFlow)
232 {
233 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
234 {
235 if constexpr(cgt::all_same_c<H, Ts...>)
236 return std::array{ std::get<i>(A) * std::get<i>(T) ... };
237 else
238 return std::tuple{ std::get<i>(A) * std::get<i>(T) ... };
239 });
240 }
241
242 template<typename E, std::size_t N, typename H, typename... Ts>
243 requires (N == sizeof...(Ts) + 1) &&
244 ( !( cgt::numerical_c<E> && (cgt::numerical_c<H> && ... && cgt::numerical_c<Ts>)) )
245 constexpr decltype(auto) operator*
246 (std::tuple<H, Ts...> const& T, std::array<E, N> const& A) noexcept(!cpg::bDetectOverFlow)
247 {
248 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
249 {
250 if constexpr(cgt::all_same_c<H, Ts...>)
251 return std::array{ std::get<i>(T) * std::get<i>(A) ... };
252 else
253 return std::tuple{ std::get<i>(T) * std::get<i>(A) ... };
254 });
255 }
256
258
259 template<cgt::numerical_c E, std::size_t N, cgt::numerical_c H, cgt::numerical_c... Ts>
260 requires (N == sizeof...(Ts) + 1)
261 constexpr decltype(auto) operator/
262 (std::array<E, N> const& A, std::tuple<H, Ts...> const& T) noexcept(!cpg::bDetectOverFlow)
263 {
264 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
265 {
266 if constexpr(cgt::all_same_c<H, Ts...>)
267 return std::array{ cgt::sbo(std::get<i>(A)) / cgt::sbo(std::get<i>(T)) ... };
268 else
269 return std::tuple{ cgt::sbo(std::get<i>(A)) / cgt::sbo(std::get<i>(T)) ... };
270 });
271 }
272
273 template<cgt::numerical_c E, std::size_t N, cgt::numerical_c H, cgt::numerical_c... Ts>
274 requires (N == sizeof...(Ts) + 1)
275 constexpr decltype(auto) operator/
276 (std::tuple<H, Ts...> const& T, std::array<E, N> const& A) noexcept(!cpg::bDetectOverFlow)
277 {
278 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
279 {
280 if constexpr(cgt::all_same_c<H, Ts...>)
281 return std::array{ cgt::sbo(std::get<i>(T)) / cgt::sbo(std::get<i>(A)) ... };
282 else
283 return std::tuple{ cgt::sbo(std::get<i>(T)) / cgt::sbo(std::get<i>(A)) ... };
284 });
285 }
286
287 template<typename E, std::size_t N, typename H, typename... Ts>
288 requires (N == sizeof...(Ts) + 1) &&
289 ( !(cgt::numerical_c<E> && (cgt::numerical_c<H> && ... && cgt::numerical_c<Ts>)) )
290 constexpr decltype(auto) operator/
291 (std::array<E, N> const& A, std::tuple<H, Ts...> const& T) noexcept(!cpg::bDetectOverFlow)
292 {
293 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
294 {
295 if constexpr(cgt::all_same_c<H, Ts...>)
296 return std::array{ std::get<i>(A) / std::get<i>(T) ... };
297 else
298 return std::tuple{ std::get<i>(A) / std::get<i>(T) ... };
299 });
300 }
301
302 template<typename E, std::size_t N, typename H, typename... Ts>
303 requires (N == sizeof...(Ts) + 1) &&
304 ( !( cgt::numerical_c<E> && (cgt::numerical_c<H> && ... && cgt::numerical_c<Ts>)) )
305 constexpr decltype(auto) operator/
306 (std::tuple<H, Ts...> const& T, std::array<E, N> const& A) noexcept(!cpg::bDetectOverFlow)
307 {
308 return cgt::for_stallion<N>([&]<auto...i>(cgt::sequence<i...>)
309 {
310 if constexpr(cgt::all_same_c<H, Ts...>)
311 return std::array{ std::get<i>(T) / std::get<i>(A) ... };
312 else
313 return std::tuple{ std::get<i>(T) / std::get<i>(A) ... };
314 });
315 }
316}
317// end of namespace std
318
319#endif
320// end of file
constexpr decltype(auto) for_stallion(WorkType &&work, std::integer_sequence< T, Indices... >, ArgTypes &&... args)
Definition: cpg_types.hpp:3858
make_signed_t< std::common_type_t< std::remove_cvref_t< Types >... > > common_signed_t
Definition: cpg_types.hpp:1012
constexpr auto sbo(T &&value) noexcept(!cpg::bDetectOverFlow)
Definition: cpg_types.hpp:2549
std::integer_sequence< std::common_type_t< std::remove_cvref_t< decltype(Indices)>... >, Indices... > sequence
Definition: cpg_types.hpp:2665
constexpr const bool bDetectOverFlow
Definition: cpg_types.hpp:754
constexpr auto signed_tuple_operation(T arg, Tails... args) noexcept
constexpr decltype(auto) array_to_tuple(std::array< E, N > const &array) noexcept
constexpr decltype(auto) tuple_to_array(std::tuple< H, Ts... > const &tuple) noexcept