@@ -36,32 +36,6 @@ struct empty_variant {};
3636template <typename T>
3737struct is_empty_variant : std::false_type {};
3838
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-
6539#ifdef EIGENPY_WITH_CXX17_SUPPORT
6640
6741// / std::variant implementation
@@ -126,6 +100,90 @@ struct empty_variant<boost::variant<Alternatives...> > {
126100template <>
127101struct is_empty_variant <boost::blank> : std::true_type {};
128102
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+
129187// / Convert {boost,std}::variant<class...> alternative to a Python object.
130188// / This converter copy the alternative.
131189template <typename Variant>
@@ -225,7 +283,15 @@ struct VariantConvertible {
225283 EmptyConvertible<variant_type>::registration ();
226284 }
227285
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,
229295 bool >::type = true >
230296 void operator ()(T) {
231297 bp::implicitly_convertible<T, variant_type>();
0 commit comments