10 #if !defined(CNL_IMPL_OPERATORS_OPERATORS_H)
11 #define CNL_IMPL_OPERATORS_OPERATORS_H
13 #include "../config.h"
15 #include <type_traits>
24 template<
class Destination,
class Source>
25 [[nodiscard]] constexpr
auto operator()(Source
const& source)
const
27 return static_cast<Destination
>(source);
33 [[nodiscard]] constexpr
auto operator()(Rhs
const& rhs)
const
41 [[nodiscard]] constexpr
auto operator()(Rhs
const& rhs)
const
47 struct bitwise_not_op {
49 [[nodiscard]] constexpr
auto operator()(Rhs
const& rhs)
const
56 template<
class Lhs,
class Rhs>
57 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
64 template<
class Lhs,
class Rhs>
65 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
72 template<
class Lhs,
class Rhs>
73 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
80 template<
class Lhs,
class Rhs>
81 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
88 template<
class Lhs,
class Rhs>
89 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
95 struct bitwise_or_op {
96 template<
class Lhs,
class Rhs>
97 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
103 struct bitwise_and_op {
104 template<
class Lhs,
class Rhs>
105 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
111 struct bitwise_xor_op {
112 template<
class Lhs,
class Rhs>
113 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
119 struct shift_left_op {
120 template<
class Lhs,
class Rhs>
121 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
127 struct shift_right_op {
128 template<
class Lhs,
class Rhs>
129 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
136 template<
class Lhs,
class Rhs>
137 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
143 struct not_equal_op {
144 template<
class Lhs,
class Rhs>
145 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
151 struct less_than_op {
152 template<
class Lhs,
class Rhs>
153 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
159 struct greater_than_op {
160 template<
class Lhs,
class Rhs>
161 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
167 struct less_than_or_equal_op {
168 template<
class Lhs,
class Rhs>
169 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
175 struct greater_than_or_equal_op {
176 template<
class Lhs,
class Rhs>
177 [[nodiscard]] constexpr
auto operator()(Lhs
const& lhs, Rhs
const& rhs)
const
183 struct pre_increment_op {
185 constexpr
auto operator()(Rhs& rhs)
const
191 struct pre_decrement_op {
193 constexpr
auto operator()(Rhs& rhs)
const
199 struct post_increment_op {
201 constexpr
auto operator()(Lhs& lhs)
const
207 struct post_decrement_op {
209 constexpr
auto operator()(Lhs& lhs)
const
215 #if defined(__GNUC__)
217 #pragma GCC diagnostic push
218 #pragma GCC diagnostic ignored "-Wconversion"
219 #elif defined(_MSC_VER)
220 #pragma warning(push)
221 #pragma warning(disable : 4244)
223 struct assign_add_op {
224 using binary = add_op;
226 template<
class Lhs,
class Rhs>
227 constexpr
auto operator()(Lhs& lhs, Rhs
const& rhs)
const
233 struct assign_subtract_op {
234 using binary = subtract_op;
236 template<
class Lhs,
class Rhs>
237 constexpr
auto operator()(Lhs& lhs, Rhs
const& rhs)
const
242 #if defined(__GNUC__)
243 #pragma GCC diagnostic pop
244 #elif defined(_MSC_VER)
248 struct assign_multiply_op {
249 using binary = multiply_op;
251 template<
class Lhs,
class Rhs>
252 constexpr
auto operator()(Lhs& lhs, Rhs
const& rhs)
const
258 struct assign_divide_op {
259 using binary = divide_op;
261 template<
class Lhs,
class Rhs>
262 constexpr
auto operator()(Lhs& lhs, Rhs
const& rhs)
const
268 struct assign_modulo_op {
269 using binary = modulo_op;
271 template<
class Lhs,
class Rhs>
272 constexpr
auto operator()(Lhs& lhs, Rhs
const& rhs)
const
278 struct assign_bitwise_or_op {
279 using binary = bitwise_or_op;
281 template<
class Lhs,
class Rhs>
282 constexpr
auto operator()(Lhs& lhs, Rhs
const& rhs)
const
288 struct assign_bitwise_and_op {
289 using binary = bitwise_and_op;
291 template<
class Lhs,
class Rhs>
292 constexpr
auto operator()(Lhs& lhs, Rhs
const& rhs)
const
298 struct assign_bitwise_xor_op {
299 using binary = bitwise_xor_op;
301 template<
class Lhs,
class Rhs>
302 constexpr
auto operator()(Lhs& lhs, Rhs
const& rhs)
const
308 struct assign_shift_left_op {
309 using binary = shift_left_op;
311 template<
class Lhs,
class Rhs>
312 constexpr
auto operator()(Lhs& lhs, Rhs
const& rhs)
const
318 struct assign_shift_right_op {
319 using binary = shift_right_op;
321 template<
class Lhs,
class Rhs>
322 constexpr
auto operator()(Lhs& lhs, Rhs
const& rhs)
const
332 inline constexpr
auto is_unary_arithmetic_op =
false;
334 inline constexpr
auto is_unary_arithmetic_op<minus_op> =
true;
336 inline constexpr
auto is_unary_arithmetic_op<plus_op> =
true;
338 inline constexpr
auto is_unary_arithmetic_op<bitwise_not_op> =
true;
341 inline constexpr
auto is_binary_arithmetic_op =
false;
343 inline constexpr
auto is_binary_arithmetic_op<add_op> =
true;
345 inline constexpr
auto is_binary_arithmetic_op<subtract_op> =
true;
347 inline constexpr
auto is_binary_arithmetic_op<multiply_op> =
true;
349 inline constexpr
auto is_binary_arithmetic_op<divide_op> =
true;
351 inline constexpr
auto is_binary_arithmetic_op<modulo_op> =
true;
353 inline constexpr
auto is_binary_arithmetic_op<bitwise_or_op> =
true;
355 inline constexpr
auto is_binary_arithmetic_op<bitwise_and_op> =
true;
357 inline constexpr
auto is_binary_arithmetic_op<bitwise_xor_op> =
true;
360 inline constexpr
auto is_shift_op =
false;
362 inline constexpr
auto is_shift_op<shift_left_op> =
true;
364 inline constexpr
auto is_shift_op<shift_right_op> =
true;
367 inline constexpr
auto is_comparison_op =
false;
369 inline constexpr
auto is_comparison_op<equal_op> =
true;
371 inline constexpr
auto is_comparison_op<not_equal_op> =
true;
373 inline constexpr
auto is_comparison_op<less_than_op> =
true;
375 inline constexpr
auto is_comparison_op<greater_than_op> =
true;
377 inline constexpr
auto is_comparison_op<less_than_or_equal_op> =
true;
379 inline constexpr
auto is_comparison_op<greater_than_or_equal_op> =
true;
382 inline constexpr
auto is_binary_op = is_binary_arithmetic_op<T> || is_shift_op<T> || is_comparison_op<T>;
385 inline constexpr
auto is_prefix_op =
false;
387 inline constexpr
auto is_prefix_op<pre_increment_op> =
true;
389 inline constexpr
auto is_prefix_op<pre_decrement_op> =
true;
392 inline constexpr
auto is_postfix_op =
false;
394 inline constexpr
auto is_postfix_op<post_increment_op> =
true;
396 inline constexpr
auto is_postfix_op<post_decrement_op> =
true;
399 inline constexpr
auto is_compound_assign_op =
false;
401 inline constexpr
auto is_compound_assign_op<assign_add_op> =
true;
403 inline constexpr
auto is_compound_assign_op<assign_subtract_op> =
true;
405 inline constexpr
auto is_compound_assign_op<assign_multiply_op> =
true;
407 inline constexpr
auto is_compound_assign_op<assign_divide_op> =
true;
409 inline constexpr
auto is_compound_assign_op<assign_modulo_op> =
true;
411 inline constexpr
auto is_compound_assign_op<assign_bitwise_or_op> =
true;
413 inline constexpr
auto is_compound_assign_op<assign_bitwise_and_op> =
true;
415 inline constexpr
auto is_compound_assign_op<assign_bitwise_xor_op> =
true;
417 inline constexpr
auto is_compound_assign_op<assign_shift_left_op> =
true;
419 inline constexpr
auto is_compound_assign_op<assign_shift_right_op> =
true;
422 inline constexpr
auto is_op = is_unary_arithmetic_op<T> || is_binary_arithmetic_op<T> || is_shift_op<T> || is_comparison_op<T> || is_prefix_op<T> || is_postfix_op<T> || is_compound_assign_op<T>;
424 inline constexpr
auto is_op<convert_op> =
true;
427 concept unary_arithmetic_op = is_unary_arithmetic_op<T>;
429 concept binary_arithmetic_op = is_binary_arithmetic_op<T>;
431 concept shift_op = is_shift_op<T>;
433 concept comparison_op = is_comparison_op<T>;
435 concept binary_op = is_binary_op<T>;
437 concept prefix_op = is_prefix_op<T>;
439 concept postfix_op = is_postfix_op<T>;
441 concept compound_assign_op = is_compound_assign_op<T>;
443 concept op = is_op<T>;
448 template<op Operator,
class... Operands>
449 using op_result = decltype(Operator()(std::declval<Operands>()...));
454 template<prefix_op Operator>
455 struct pre_to_assign;
458 struct pre_to_assign<pre_increment_op> : std::type_identity<assign_add_op> {
462 struct pre_to_assign<pre_decrement_op> : std::type_identity<assign_subtract_op> {
465 template<postfix_op Operator>
466 struct post_to_assign;
469 struct post_to_assign<post_increment_op> : std::type_identity<assign_add_op> {
473 struct post_to_assign<post_decrement_op> : std::type_identity<assign_subtract_op> {
478 #endif // CNL_IMPL_OPERATORS_OPERATORS_H