@@ -30,6 +30,38 @@ struct VariantVisitorType {};
3030template <typename Variant>
3131struct VariantAlternatives {};
3232
33+ template <typename Variant>
34+ struct empty_variant {};
35+
36+ template <typename T>
37+ struct is_empty_variant : std::false_type {};
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+
3365#ifdef EIGENPY_WITH_CXX17_SUPPORT
3466
3567// / std::variant implementation
@@ -45,7 +77,7 @@ struct VariantVisitorType<ResultType, std::variant<Alternatives...> > {
4577 }
4678
4779 result_type operator ()(std::monostate) const {
48- return boost::python:: incref (boost::python ::object ().ptr ()); // None
80+ return bp:: incref (bp ::object ().ptr ()); // None
4981 }
5082};
5183
@@ -54,6 +86,14 @@ struct VariantAlternatives<std::variant<Alternatives...> > {
5486 typedef boost::mpl::vector<Alternatives...> types;
5587};
5688
89+ template <typename ... Alternatives>
90+ struct empty_variant <std::variant<Alternatives...> > {
91+ typedef std::monostate type;
92+ };
93+
94+ template <>
95+ struct is_empty_variant <std::monostate> : std::true_type {};
96+
5797#endif
5898
5999// / boost::variant implementation
@@ -69,7 +109,7 @@ struct VariantVisitorType<ResultType, boost::variant<Alternatives...> >
69109 }
70110
71111 result_type operator ()(boost::blank) const {
72- return boost::python:: incref (boost::python ::object ().ptr ()); // None
112+ return bp:: incref (bp ::object ().ptr ()); // None
73113 }
74114};
75115
@@ -78,6 +118,14 @@ struct VariantAlternatives<boost::variant<Alternatives...> > {
78118 typedef typename boost::variant<Alternatives...>::types types;
79119};
80120
121+ template <typename ... Alternatives>
122+ struct empty_variant <boost::variant<Alternatives...> > {
123+ typedef boost::blank type;
124+ };
125+
126+ template <>
127+ struct is_empty_variant <boost::blank> : std::true_type {};
128+
81129// / Convert {boost,std}::variant<class...> alternative to a Python object.
82130// / This converter copy the alternative.
83131template <typename Variant>
@@ -92,16 +140,19 @@ struct VariantValueToObject : VariantVisitorType<PyObject*, Variant> {
92140
93141 template <typename T>
94142 result_type operator ()(T& t) const {
95- return boost::python:: incref (boost::python ::object (t).ptr ());
143+ return bp:: incref (bp ::object (t).ptr ());
96144 }
97145
98146 using Base::operator ();
99147};
100148
149+ // / Trait to detect if T is a class or an union
101150template <typename T>
102151struct is_class_or_union
103152 : std::integral_constant<bool , std::is_class<T>::value ||
104153 std::is_union<T>::value> {};
154+
155+ // / Trait to remove cvref and call is_class_or_union
105156template <typename T>
106157struct is_class_or_union_remove_cvref
107158 : is_class_or_union<typename std::remove_cv<
@@ -110,7 +161,7 @@ struct is_class_or_union_remove_cvref
110161// / Convert {boost,std}::variant<class...> alternative reference to a Python
111162// / object. This converter return the alternative reference. The code that
112163// / create the reference holder is taken from \see
113- // / boost::python ::to_python_indirect.
164+ // / bp ::to_python_indirect.
114165template <typename Variant>
115166struct VariantRefToObject : VariantVisitorType<PyObject*, Variant> {
116167 typedef VariantVisitorType<PyObject*, Variant> Base;
@@ -125,22 +176,22 @@ struct VariantRefToObject : VariantVisitorType<PyObject*, Variant> {
125176 typename std::enable_if<!is_class_or_union_remove_cvref<T>::value,
126177 bool >::type = true >
127178 result_type operator ()(T t) const {
128- return boost::python:: incref (boost::python ::object (t).ptr ());
179+ return bp:: incref (bp ::object (t).ptr ());
129180 }
130181
131182 template <typename T,
132183 typename std::enable_if<is_class_or_union_remove_cvref<T>::value,
133184 bool >::type = true >
134185 result_type operator ()(T& t) const {
135- return boost::python ::detail::make_reference_holder::execute (&t);
186+ return bp ::detail::make_reference_holder::execute (&t);
136187 }
137188
138189 // / Copy the object when it's None
139190 using Base::operator ();
140191};
141192
142193// / Converter used in \see ReturnInternalVariant.
143- // / This is inspired by \see boost::python ::reference_existing_object.
194+ // / This is inspired by \see bp ::reference_existing_object.
144195// / It will call \see VariantRefToObject to extract the alternative
145196// / reference.
146197template <typename Variant>
@@ -156,8 +207,7 @@ struct VariantConverter {
156207
157208#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
158209 PyTypeObject const * get_pytype () const {
159- return boost::python::converter::registered_pytype<
160- variant_type>::get_pytype ();
210+ return bp::converter::registered_pytype<variant_type>::get_pytype ();
161211 }
162212#endif
163213 };
@@ -169,19 +219,26 @@ template <typename Variant>
169219struct VariantImplicitlyConvertible {
170220 typedef Variant variant_type;
171221
172- template <class T >
222+ template <class T , typename std::enable_if<is_empty_variant<T>::value,
223+ bool >::type = true >
224+ void operator ()(T) {
225+ EmptyConvertible<variant_type>::registration ();
226+ }
227+
228+ template <class T , typename std::enable_if<!is_empty_variant<T>::value,
229+ bool >::type = true >
173230 void operator ()(T) {
174- boost::python ::implicitly_convertible<T, variant_type>();
231+ bp ::implicitly_convertible<T, variant_type>();
175232 }
176233};
177234
178235} // namespace details
179236
180- // / Variant of \see boost::python ::return_internal_reference that
237+ // / Variant of \see bp ::return_internal_reference that
181238// / extract {boost,std}::variant<class...> alternative reference before
182239// / converting it into a PyObject
183240template <typename Variant>
184- struct ReturnInternalVariant : boost::python ::return_internal_reference<> {
241+ struct ReturnInternalVariant : bp ::return_internal_reference<> {
185242 typedef Variant variant_type;
186243
187244 typedef details::VariantConverter<variant_type> result_converter;
@@ -192,7 +249,7 @@ struct ReturnInternalVariant : boost::python::return_internal_reference<> {
192249 if (PyLong_Check (result) || PyBool_Check (result) || PyFloat_Check (result)) {
193250 return result;
194251 }
195- return boost::python ::return_internal_reference<>::postcall (args_, result);
252+ return bp ::return_internal_reference<>::postcall (args_, result);
196253 }
197254};
198255
@@ -208,12 +265,12 @@ struct ReturnInternalVariant : boost::python::return_internal_reference<> {
208265// / };
209266// / ...
210267// / void expose() {
211- // / boost::python ::class_<Struct1>("Struct1", bp::init<>());
212- // / boost::python ::class_<Struct2>("Struct1", bp::init<>())
268+ // / bp ::class_<Struct1>("Struct1", bp::init<>());
269+ // / bp ::class_<Struct2>("Struct1", bp::init<>())
213270// / typedef eigenpy::VariantConverter<MyVariant> Converter;
214271// / Converter::registration();
215272// /
216- // / boost::python ::class_<VariantHolder>("VariantHolder", bp::init<>())
273+ // / bp ::class_<VariantHolder>("VariantHolder", bp::init<>())
217274// / .add_property("variant",
218275// / bp::make_getter(&VariantHolder::variant,
219276// / Converter::return_internal_reference()),
@@ -228,7 +285,7 @@ struct VariantConverter {
228285 typedef details::VariantValueToObject<variant_type> variant_to_value;
229286 typedef typename details::VariantAlternatives<variant_type>::types types;
230287
231- boost::python ::to_python_converter<variant_type, variant_to_value>();
288+ bp ::to_python_converter<variant_type, variant_to_value>();
232289 boost::mpl::for_each<types>(
233290 details::VariantImplicitlyConvertible<variant_type>());
234291 }
0 commit comments