1 #ifndef UTILS_WRAPPER_H_INCLUDED
2 #define UTILS_WRAPPER_H_INCLUDED
6 #define UTILS_OP_CHECKER(name, op) \
7 template<typename T, typename U> Nop operator op(const T&, const U&); \
8 template<typename T, typename U=T> \
9 struct name##Exists { \
10 enum { value = !::std::is_same<decltype(std::declval<T>() op std::declval<U>()), Nop>::value }; \
13 #define UTILS_UNARY_OP_CHECKER(name, op) \
14 template<typename T> Nop operator op(T&); \
15 template<typename T> \
16 struct name##Exists { \
17 enum { value = !::std::is_same<decltype(op *std::declval<T*>()), Nop>::value }; \
20 #define UTILS_IMPL_WRAPPER_OP(name, op) \
21 template<typename U, typename std::enable_if_t<check:: name##Exists<T, U>::value>* = nullptr> \
22 Wrapper operator op(const U& rhs) const { \
23 return Wrapper(m_data op rhs); \
25 template<typename U, typename std::enable_if_t<check:: name##Exists<T, U>::value>* = nullptr> \
26 Wrapper& operator op##=(const U& rhs) { \
27 m_data = m_data op rhs; \
31 #define UTILS_IMPL_WRAPPER_SELF_OP(name, op) \
32 template<typename T, typename TAG, typename std::enable_if_t<check:: name##Exists<T>::value>* = nullptr> \
33 Wrapper<T, TAG> operator op(const Wrapper<T, TAG>& lhs, const Wrapper<T, TAG>& rhs) { \
34 return Wrapper<T, TAG>(lhs.to_inner() op rhs.to_inner()); \
36 template<typename T, typename TAG, typename std::enable_if_t<check:: name##Exists<T>::value>* = nullptr> \
37 Wrapper<T, TAG>& operator op##=(Wrapper<T, TAG>& lhs, const Wrapper<T, TAG>& rhs) { \
38 lhs.to_inner() = lhs.to_inner() op rhs.to_inner(); \
39 return Wrapper<T, TAG>(lhs); \
42 #define UTILS_IMPL_WRAPPER_UNARY_OP(name, op, c) \
43 template<typename T, typename TAG, typename std::enable_if_t<check:: name##Exists<T>::value>* = nullptr> \
44 Wrapper<T, TAG> operator op(c Wrapper<T, TAG>& w) { \
45 return Wrapper<T, TAG>(op w.to_inner()); \
48 #define UTILS_IMPL_WRAPPER_COMP(name, op) \
49 template<typename U, typename std::enable_if_t<check:: name##Exists<T, U>::value>* = nullptr> \
50 bool operator op(const U& rhs) const { \
51 return m_data op rhs; \
53 template<typename U, typename std::enable_if_t<check:: name##Exists<T, U>::value && check::EqualsExists<T, U>::value>* = nullptr> \
54 bool operator op##=(const U& rhs) const { \
55 return m_data op rhs || m_data == rhs; \
58 #define UTILS_IMPL_WRAPPER_SELF_COMP(name, op) \
59 template<typename T, typename TAG, typename std::enable_if_t<check:: name##Exists<T>::value>* = nullptr> \
60 bool operator op(const Wrapper<T, TAG>& lhs, const Wrapper<T, TAG>& rhs) { \
61 return lhs.to_inner() op rhs.to_inner(); \
63 template<typename T, typename TAG, typename std::enable_if_t<check:: name##Exists<T>::value && check::EqualsExists<T>::value>* = nullptr> \
64 bool operator op##=(const Wrapper<T, TAG>& lhs, const Wrapper<T, TAG>& rhs) { \
65 return lhs.to_inner() op rhs.to_inner() || lhs.to_inner() == rhs.to_inner(); \
72 UTILS_OP_CHECKER(Equals, ==)
73 UTILS_OP_CHECKER(Add, +)
74 UTILS_OP_CHECKER(Sub, -)
75 UTILS_UNARY_OP_CHECKER(Neg, -)
76 UTILS_OP_CHECKER(Div, /)
77 UTILS_OP_CHECKER(Mul, *)
78 UTILS_OP_CHECKER(And, &)
79 UTILS_OP_CHECKER(Or, |)
80 UTILS_UNARY_OP_CHECKER(Not, ~)
81 UTILS_UNARY_OP_CHECKER(Incr, ++)
82 UTILS_UNARY_OP_CHECKER(Decr, --)
83 UTILS_OP_CHECKER(LShift, <<)
84 UTILS_OP_CHECKER(RShift, >>)
85 UTILS_OP_CHECKER(Mod, %)
86 UTILS_OP_CHECKER(Greater, >)
87 UTILS_OP_CHECKER(Lesser, <)
95 template<typename T, typename TAG>
102 Wrapper(T data = T()) : m_data(data) {}
103 const T& to_inner()
const {
return m_data; }
104 T& to_inner() {
return m_data; }
105 explicit operator T()
const {
return to_inner(); }
108 return m_data == rhs;
110 template<typename std::enable_if_t<check::EqualsExists<T>::value>* =
nullptr>
111 bool operator==(
const Wrapper& rhs)
const {
112 return m_data == rhs.m_data;
116 return m_data != rhs;
118 template<typename std::enable_if_t<check::EqualsExists<T>::value>* =
nullptr>
119 bool operator!=(
const Wrapper& rhs)
const {
120 return !(m_data == rhs.m_data);
122 UTILS_IMPL_WRAPPER_OP(Add, +)
123 UTILS_IMPL_WRAPPER_OP(Sub, -)
124 UTILS_IMPL_WRAPPER_OP(Div, /)
125 UTILS_IMPL_WRAPPER_OP(Mul, *)
126 UTILS_IMPL_WRAPPER_OP(And, &)
127 UTILS_IMPL_WRAPPER_OP(Or, |)
128 UTILS_IMPL_WRAPPER_OP(LShift, <<)
129 UTILS_IMPL_WRAPPER_OP(RShift, >>)
130 UTILS_IMPL_WRAPPER_OP(Mod, %)
131 UTILS_IMPL_WRAPPER_COMP(Greater, >)
132 UTILS_IMPL_WRAPPER_COMP(Lesser, <)
134 UTILS_IMPL_WRAPPER_SELF_OP(Add, +)
135 UTILS_IMPL_WRAPPER_SELF_OP(Sub, -)
136 UTILS_IMPL_WRAPPER_SELF_OP(Div, /)
137 UTILS_IMPL_WRAPPER_SELF_OP(Mul, *)
138 UTILS_IMPL_WRAPPER_SELF_OP(And, &)
139 UTILS_IMPL_WRAPPER_SELF_OP(Or, |)
140 UTILS_IMPL_WRAPPER_SELF_OP(LShift, <<)
141 UTILS_IMPL_WRAPPER_SELF_OP(RShift, >>)
142 UTILS_IMPL_WRAPPER_SELF_OP(Mod, %)
143 UTILS_IMPL_WRAPPER_SELF_COMP(Greater, >)
144 UTILS_IMPL_WRAPPER_SELF_COMP(Lesser, <)
145 UTILS_IMPL_WRAPPER_UNARY_OP(Neg, -, const)
146 UTILS_IMPL_WRAPPER_UNARY_OP(Not, ~, const)
147 UTILS_IMPL_WRAPPER_UNARY_OP(Incr, ++,)
148 template<typename T, typename TAG, typename std::enable_if_t<check::IncrExists<T>::value>* =
nullptr>
154 UTILS_IMPL_WRAPPER_UNARY_OP(Decr, --,)
155 template<typename T, typename TAG, typename std::enable_if_t<check::DecrExists<T>::value>* =
nullptr>
156 Wrapper<T, TAG> operator--(Wrapper<T, TAG>& lhs,
int) {
161 template<typename T, typename TAG, typename std::enable_if_t<check::LShiftExists<std::ostream, T>::value>* =
nullptr>
162 std::ostream& operator<<(std::ostream& lhs,
const Wrapper<T, TAG>& w) {
163 return lhs<<w.to_inner();
174 template<
typename T,
typename TAG>
183 template<
typename T,
typename TAG>
184 struct hash<utils::Wrapper<T, TAG>> {
186 return std::hash<T>()(w.to_inner());
189 template<
typename T,
typename TAG>
190 struct hash<utils::StrongWrapper<T, TAG>> {
192 return std::hash<T>()(w.to_inner());
197 #endif // UTILS_WRAPPER_H_INCLUDED