1 | /* |
2 | pybind11/operator.h: Metatemplates for operator overloading |
3 | |
4 | Copyright (c) 2016 Wenzel Jakob <[email protected]> |
5 | |
6 | All rights reserved. Use of this source code is governed by a |
7 | BSD-style license that can be found in the LICENSE file. |
8 | */ |
9 | |
10 | #pragma once |
11 | |
12 | #include "pybind11.h" |
13 | |
14 | PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) |
15 | PYBIND11_NAMESPACE_BEGIN(detail) |
16 | |
17 | /// Enumeration with all supported operator types |
18 | enum op_id : int { |
19 | op_add, |
20 | op_sub, |
21 | op_mul, |
22 | op_div, |
23 | op_mod, |
24 | op_divmod, |
25 | op_pow, |
26 | op_lshift, |
27 | op_rshift, |
28 | op_and, |
29 | op_xor, |
30 | op_or, |
31 | op_neg, |
32 | op_pos, |
33 | op_abs, |
34 | op_invert, |
35 | op_int, |
36 | op_long, |
37 | op_float, |
38 | op_str, |
39 | op_cmp, |
40 | op_gt, |
41 | op_ge, |
42 | op_lt, |
43 | op_le, |
44 | op_eq, |
45 | op_ne, |
46 | op_iadd, |
47 | op_isub, |
48 | op_imul, |
49 | op_idiv, |
50 | op_imod, |
51 | op_ilshift, |
52 | op_irshift, |
53 | op_iand, |
54 | op_ixor, |
55 | op_ior, |
56 | op_complex, |
57 | op_bool, |
58 | op_nonzero, |
59 | op_repr, |
60 | op_truediv, |
61 | op_itruediv, |
62 | op_hash |
63 | }; |
64 | |
65 | enum op_type : int { |
66 | op_l, /* base type on left */ |
67 | op_r, /* base type on right */ |
68 | op_u /* unary operator */ |
69 | }; |
70 | |
71 | struct self_t {}; |
72 | static const self_t self = self_t(); |
73 | |
74 | /// Type for an unused type slot |
75 | struct undefined_t {}; |
76 | |
77 | /// Don't warn about an unused variable |
78 | inline self_t __self() { return self; } |
79 | |
80 | /// base template of operator implementations |
81 | template <op_id, op_type, typename B, typename L, typename R> |
82 | struct op_impl {}; |
83 | |
84 | /// Operator implementation generator |
85 | template <op_id id, op_type ot, typename L, typename R> |
86 | struct op_ { |
87 | static constexpr bool op_enable_if_hook = true; |
88 | template <typename Class, typename... Extra> |
89 | void execute(Class &cl, const Extra &...) const { |
90 | using Base = typename Class::type; |
91 | using L_type = conditional_t<std::is_same<L, self_t>::value, Base, L>; |
92 | using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>; |
93 | using op = op_impl<id, ot, Base, L_type, R_type>; |
94 | cl.def(op::name(), &op::execute, is_operator(), extra...); |
95 | } |
96 | template <typename Class, typename... Extra> |
97 | void execute_cast(Class &cl, const Extra &...) const { |
98 | using Base = typename Class::type; |
99 | using L_type = conditional_t<std::is_same<L, self_t>::value, Base, L>; |
100 | using R_type = conditional_t<std::is_same<R, self_t>::value, Base, R>; |
101 | using op = op_impl<id, ot, Base, L_type, R_type>; |
102 | cl.def(op::name(), &op::execute_cast, is_operator(), extra...); |
103 | } |
104 | }; |
105 | |
106 | #define PYBIND11_BINARY_OPERATOR(id, rid, op, expr) \ |
107 | template <typename B, typename L, typename R> \ |
108 | struct op_impl<op_##id, op_l, B, L, R> { \ |
109 | static char const *name() { return "__" #id "__"; } \ |
110 | static auto execute(const L &l, const R &r) -> decltype(expr) { return (expr); } \ |
111 | static B execute_cast(const L &l, const R &r) { return B(expr); } \ |
112 | }; \ |
113 | template <typename B, typename L, typename R> \ |
114 | struct op_impl<op_##id, op_r, B, L, R> { \ |
115 | static char const *name() { return "__" #rid "__"; } \ |
116 | static auto execute(const R &r, const L &l) -> decltype(expr) { return (expr); } \ |
117 | static B execute_cast(const R &r, const L &l) { return B(expr); } \ |
118 | }; \ |
119 | inline op_<op_##id, op_l, self_t, self_t> op(const self_t &, const self_t &) { \ |
120 | return op_<op_##id, op_l, self_t, self_t>(); \ |
121 | } \ |
122 | template <typename T> \ |
123 | op_<op_##id, op_l, self_t, T> op(const self_t &, const T &) { \ |
124 | return op_<op_##id, op_l, self_t, T>(); \ |
125 | } \ |
126 | template <typename T> \ |
127 | op_<op_##id, op_r, T, self_t> op(const T &, const self_t &) { \ |
128 | return op_<op_##id, op_r, T, self_t>(); \ |
129 | } |
130 | |
131 | #define PYBIND11_INPLACE_OPERATOR(id, op, expr) \ |
132 | template <typename B, typename L, typename R> \ |
133 | struct op_impl<op_##id, op_l, B, L, R> { \ |
134 | static char const *name() { return "__" #id "__"; } \ |
135 | static auto execute(L &l, const R &r) -> decltype(expr) { return expr; } \ |
136 | static B execute_cast(L &l, const R &r) { return B(expr); } \ |
137 | }; \ |
138 | template <typename T> \ |
139 | op_<op_##id, op_l, self_t, T> op(const self_t &, const T &) { \ |
140 | return op_<op_##id, op_l, self_t, T>(); \ |
141 | } |
142 | |
143 | #define PYBIND11_UNARY_OPERATOR(id, op, expr) \ |
144 | template <typename B, typename L> \ |
145 | struct op_impl<op_##id, op_u, B, L, undefined_t> { \ |
146 | static char const *name() { return "__" #id "__"; } \ |
147 | static auto execute(const L &l) -> decltype(expr) { return expr; } \ |
148 | static B execute_cast(const L &l) { return B(expr); } \ |
149 | }; \ |
150 | inline op_<op_##id, op_u, self_t, undefined_t> op(const self_t &) { \ |
151 | return op_<op_##id, op_u, self_t, undefined_t>(); \ |
152 | } |
153 | |
154 | PYBIND11_BINARY_OPERATOR(sub, rsub, operator-, l - r) |
155 | PYBIND11_BINARY_OPERATOR(add, radd, operator+, l + r) |
156 | PYBIND11_BINARY_OPERATOR(mul, rmul, operator*, l *r) |
157 | PYBIND11_BINARY_OPERATOR(truediv, rtruediv, operator/, l / r) |
158 | PYBIND11_BINARY_OPERATOR(mod, rmod, operator%, l % r) |
159 | PYBIND11_BINARY_OPERATOR(lshift, rlshift, operator<<, l << r) |
160 | PYBIND11_BINARY_OPERATOR(rshift, rrshift, operator>>, l >> r) |
161 | PYBIND11_BINARY_OPERATOR(and, rand, operator&, l &r) |
162 | PYBIND11_BINARY_OPERATOR(xor, rxor, operator^, l ^ r) |
163 | PYBIND11_BINARY_OPERATOR(eq, eq, operator==, l == r) |
164 | PYBIND11_BINARY_OPERATOR(ne, ne, operator!=, l != r) |
165 | PYBIND11_BINARY_OPERATOR(or, ror, operator|, l | r) |
166 | PYBIND11_BINARY_OPERATOR(gt, lt, operator>, l > r) |
167 | PYBIND11_BINARY_OPERATOR(ge, le, operator>=, l >= r) |
168 | PYBIND11_BINARY_OPERATOR(lt, gt, operator<, l < r) |
169 | PYBIND11_BINARY_OPERATOR(le, ge, operator<=, l <= r) |
170 | // PYBIND11_BINARY_OPERATOR(pow, rpow, pow, std::pow(l, r)) |
171 | PYBIND11_INPLACE_OPERATOR(iadd, operator+=, l += r) |
172 | PYBIND11_INPLACE_OPERATOR(isub, operator-=, l -= r) |
173 | PYBIND11_INPLACE_OPERATOR(imul, operator*=, l *= r) |
174 | PYBIND11_INPLACE_OPERATOR(itruediv, operator/=, l /= r) |
175 | PYBIND11_INPLACE_OPERATOR(imod, operator%=, l %= r) |
176 | PYBIND11_INPLACE_OPERATOR(ilshift, operator<<=, l <<= r) |
177 | PYBIND11_INPLACE_OPERATOR(irshift, operator>>=, l >>= r) |
178 | PYBIND11_INPLACE_OPERATOR(iand, operator&=, l &= r) |
179 | PYBIND11_INPLACE_OPERATOR(ixor, operator^=, l ^= r) |
180 | PYBIND11_INPLACE_OPERATOR(ior, operator|=, l |= r) |
181 | PYBIND11_UNARY_OPERATOR(neg, operator-, -l) |
182 | PYBIND11_UNARY_OPERATOR(pos, operator+, +l) |
183 | // WARNING: This usage of `abs` should only be done for existing STL overloads. |
184 | // Adding overloads directly in to the `std::` namespace is advised against: |
185 | // https://en.cppreference.com/w/cpp/language/extending_std |
186 | PYBIND11_UNARY_OPERATOR(abs, abs, std::abs(l)) |
187 | PYBIND11_UNARY_OPERATOR(hash, hash, std::hash<L>()(l)) |
188 | PYBIND11_UNARY_OPERATOR(invert, operator~, (~l)) |
189 | PYBIND11_UNARY_OPERATOR(bool, operator!, !!l) |
190 | PYBIND11_UNARY_OPERATOR(int, int_, (int) l) |
191 | PYBIND11_UNARY_OPERATOR(float, float_, (double) l) |
192 | |
193 | #undef PYBIND11_BINARY_OPERATOR |
194 | #undef PYBIND11_INPLACE_OPERATOR |
195 | #undef PYBIND11_UNARY_OPERATOR |
196 | PYBIND11_NAMESPACE_END(detail) |
197 | |
198 | using detail::self; |
199 | // Add named operators so that they are accessible via `py::`. |
200 | using detail::hash; |
201 | |
202 | PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) |
203 | |