-
Notifications
You must be signed in to change notification settings - Fork 1
/
binary_op_impl.hpp
132 lines (110 loc) · 4.25 KB
/
binary_op_impl.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#ifndef PQS_BINARY_OP_IMPL_HPP_INCLUDED
#define PQS_BINARY_OP_IMPL_HPP_INCLUDED
/*
Copyright (c) 2005-2020 Andy Little
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
/*
The binary_operation struct has one member 'type' which
represents the type of the result of a binary operation.
such as +, -, *, << ,!= ,== etc. The Op parameter 'token'
is represented by the Op tokens provided in
"pqs/meta/binary_op_tags.hpp".
e.g for the result type of addition of 2 ints the typedef
would look like binary_op<int,plus,int>::type.
*/
#include <type_traits>
#include <pqs/bits/config.hpp>
#include <pqs/bits/undefined_arg.hpp>
#include <pqs/bits/meta/is_any_type.hpp>
#include <pqs/bits/meta/binary_op_tags.hpp>
#include <pqs/bits/meta/binary_operator_types.hpp>
#include <pqs/bits/meta/is_runtime_type.hpp>
#include <pqs/bits/meta/or.hpp>
#include <pqs/bits/meta/and.hpp>
#include <pqs/bits/meta/not.hpp>
namespace pqs{
namespace meta{
template <typename A, typename B>
struct are_arithmetic : pqs::meta::and_<
std::is_arithmetic<A>,
std::is_arithmetic<B>
>{};
} //meta
template <typename Tl, typename Op, typename TR>
struct binary_op;
template <typename Tl, typename Op, typename TR>
struct is_valid_binary_op;
namespace impl {
template <
typename A,
typename Op,
typename B
>
struct binary_op_impl : pqs::undefined_arg<A,Op,B>{};
template <
typename Left,
typename Op,
typename Right
>
struct is_valid_binary_op_impl
: pqs::meta::is_any_type<typename pqs::binary_op<Left,Op,Right>::type>{};
template < typename A, typename Op, typename B>
requires
pqs::meta::is_assignment_operator<Op>::value
&& std::is_assignable_v<A,B>
struct binary_op_impl<A, Op,B> : std::add_lvalue_reference<A>{};
template < typename A, typename Op, typename B>
requires
pqs::meta::and_<
pqs::meta::are_arithmetic<A,B>,
pqs::meta::or_<
pqs::meta::is_comparison_operator<Op>,
pqs::meta::is_logical_operator<Op>
>,
pqs::meta::or_<
pqs::meta::is_runtime_type<A>,
pqs::meta::is_runtime_type<B>
>,
pqs::meta::or_<
pqs::is_valid_binary_op<A,minus,B>,
pqs::meta::and_<
std::is_same<A,bool>,
std::is_same<B,bool>
>
>
>::value
struct binary_op_impl<A,Op,B>{
typedef bool type;
};
template < typename A, typename Op, typename B>
requires
pqs::meta::or_<
pqs::meta::and_<
pqs::meta::are_arithmetic<A,B>,
pqs::meta::is_arithmetic_operator<Op>
>,
pqs::meta::and_<
std::is_integral<A>,
std::is_integral<B>,
std::integral_constant<bool,(
(pqs::meta::op_class<Op>::value == pqs::meta::op_class_t::inclusive_or) ||
(pqs::meta::op_class<Op>::value == pqs::meta::op_class_t::exclusive_or) ||
(pqs::meta::op_class<Op>::value == pqs::meta::op_class_t::bit_and) ||
(pqs::meta::op_class<Op>::value == pqs::meta::op_class_t::shift)
)>
>
>::value
struct binary_op_impl<A,Op,B> : std::common_type<A,B>{};
}//impl
}//pqs
#endif