@@ -36,32 +36,6 @@ struct empty_variant {};
36
36
template <typename T>
37
37
struct is_empty_variant : std::false_type {};
38
38
39
- // / Convert None to a {boost,std}::variant with boost::blank or std::monostate
40
- // / value
41
- template <typename Variant>
42
- struct EmptyConvertible {
43
- static void registration () {
44
- bp::converter::registry::push_back (convertible, construct,
45
- bp::type_id<Variant>());
46
- }
47
-
48
- // convertible only for None
49
- static void * convertible (PyObject* obj) {
50
- return (obj == Py_None) ? obj : nullptr ;
51
- };
52
-
53
- // construct in place
54
- static void construct (PyObject*,
55
- bp::converter::rvalue_from_python_stage1_data* data) {
56
- void * storage =
57
- reinterpret_cast <bp::converter::rvalue_from_python_storage<Variant>*>(
58
- data)
59
- ->storage .bytes ;
60
- new (storage) Variant (typename empty_variant<Variant>::type ());
61
- data->convertible = storage;
62
- };
63
- };
64
-
65
39
#ifdef EIGENPY_WITH_CXX17_SUPPORT
66
40
67
41
// / std::variant implementation
@@ -126,6 +100,90 @@ struct empty_variant<boost::variant<Alternatives...> > {
126
100
template <>
127
101
struct is_empty_variant <boost::blank> : std::true_type {};
128
102
103
+ // / Convert None to a {boost,std}::variant with boost::blank or std::monostate
104
+ // / value
105
+ template <typename Variant>
106
+ struct EmptyConvertible {
107
+ static void registration () {
108
+ bp::converter::registry::push_back (convertible, construct,
109
+ bp::type_id<Variant>());
110
+ }
111
+
112
+ // convertible only for None
113
+ static void * convertible (PyObject* obj) {
114
+ return (obj == Py_None) ? obj : nullptr ;
115
+ };
116
+
117
+ // construct in place
118
+ static void construct (PyObject*,
119
+ bp::converter::rvalue_from_python_stage1_data* data) {
120
+ void * storage =
121
+ reinterpret_cast <bp::converter::rvalue_from_python_storage<Variant>*>(
122
+ data)
123
+ ->storage .bytes ;
124
+ new (storage) Variant (typename empty_variant<Variant>::type ());
125
+ data->convertible = storage;
126
+ };
127
+ };
128
+
129
+ // / Implement convertible and expected_pytype for bool, integer and float
130
+ template <typename T, class Enable = void >
131
+ struct NumericConvertibleImpl {};
132
+
133
+ template <typename T>
134
+ struct NumericConvertibleImpl <
135
+ T, typename std::enable_if<std::is_same<T, bool >::value>::type> {
136
+ static void * convertible (PyObject* obj) {
137
+ return PyBool_Check (obj) ? obj : nullptr ;
138
+ }
139
+
140
+ static PyTypeObject const * expected_pytype () { return &PyBool_Type; }
141
+ };
142
+
143
+ template <typename T>
144
+ struct NumericConvertibleImpl <
145
+ T, typename std::enable_if<!std::is_same<T, bool >::value &&
146
+ std::is_integral<T>::value>::type> {
147
+ static void * convertible (PyObject* obj) {
148
+ // PyLong return true for bool type
149
+ return (PyLong_Check (obj) && !PyBool_Check (obj)) ? obj : nullptr ;
150
+ }
151
+
152
+ static PyTypeObject const * expected_pytype () { return &PyLong_Type; }
153
+ };
154
+
155
+ template <typename T>
156
+ struct NumericConvertibleImpl <
157
+ T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
158
+ static void * convertible (PyObject* obj) {
159
+ return PyFloat_Check (obj) ? obj : nullptr ;
160
+ }
161
+
162
+ static PyTypeObject const * expected_pytype () { return &PyFloat_Type; }
163
+ };
164
+
165
+ // / Convert numeric type to Variant without ambiguity
166
+ template <typename T, typename Variant>
167
+ struct NumericConvertible {
168
+ static void registration () {
169
+ bp::converter::registry::push_back (
170
+ &convertible, &bp::converter::implicit<T, Variant>::construct,
171
+ bp::type_id<Variant>()
172
+ #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
173
+ ,
174
+ &expected_pytype
175
+ #endif
176
+ );
177
+ }
178
+
179
+ static void * convertible (PyObject* obj) {
180
+ return NumericConvertibleImpl<T>::convertible (obj);
181
+ }
182
+ static PyTypeObject const * expected_pytype () {
183
+ return NumericConvertibleImpl<T>::expected_pytype ();
184
+ }
185
+ };
186
+
129
187
// / Convert {boost,std}::variant<class...> alternative to a Python object.
130
188
// / This converter copy the alternative.
131
189
template <typename Variant>
@@ -225,7 +283,15 @@ struct VariantConvertible {
225
283
EmptyConvertible<variant_type>::registration ();
226
284
}
227
285
228
- template <class T , typename std::enable_if<!is_empty_variant<T>::value,
286
+ template <class T , typename std::enable_if<!is_empty_variant<T>::value &&
287
+ std::is_arithmetic<T>::value,
288
+ bool >::type = true >
289
+ void operator ()(T) {
290
+ NumericConvertible<T, variant_type>::registration ();
291
+ }
292
+
293
+ template <class T , typename std::enable_if<!is_empty_variant<T>::value &&
294
+ !std::is_arithmetic<T>::value,
229
295
bool >::type = true >
230
296
void operator ()(T) {
231
297
bp::implicitly_convertible<T, variant_type>();
0 commit comments