@@ -30,6 +30,38 @@ struct VariantVisitorType {};
30
30
template <typename Variant>
31
31
struct VariantAlternatives {};
32
32
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
+
33
65
#ifdef EIGENPY_WITH_CXX17_SUPPORT
34
66
35
67
// / std::variant implementation
@@ -45,7 +77,7 @@ struct VariantVisitorType<ResultType, std::variant<Alternatives...> > {
45
77
}
46
78
47
79
result_type operator ()(std::monostate) const {
48
- return boost::python:: incref (boost::python ::object ().ptr ()); // None
80
+ return bp:: incref (bp ::object ().ptr ()); // None
49
81
}
50
82
};
51
83
@@ -54,6 +86,14 @@ struct VariantAlternatives<std::variant<Alternatives...> > {
54
86
typedef boost::mpl::vector<Alternatives...> types;
55
87
};
56
88
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
+
57
97
#endif
58
98
59
99
// / boost::variant implementation
@@ -69,7 +109,7 @@ struct VariantVisitorType<ResultType, boost::variant<Alternatives...> >
69
109
}
70
110
71
111
result_type operator ()(boost::blank) const {
72
- return boost::python:: incref (boost::python ::object ().ptr ()); // None
112
+ return bp:: incref (bp ::object ().ptr ()); // None
73
113
}
74
114
};
75
115
@@ -78,6 +118,14 @@ struct VariantAlternatives<boost::variant<Alternatives...> > {
78
118
typedef typename boost::variant<Alternatives...>::types types;
79
119
};
80
120
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
+
81
129
// / Convert {boost,std}::variant<class...> alternative to a Python object.
82
130
// / This converter copy the alternative.
83
131
template <typename Variant>
@@ -92,16 +140,19 @@ struct VariantValueToObject : VariantVisitorType<PyObject*, Variant> {
92
140
93
141
template <typename T>
94
142
result_type operator ()(T& t) const {
95
- return boost::python:: incref (boost::python ::object (t).ptr ());
143
+ return bp:: incref (bp ::object (t).ptr ());
96
144
}
97
145
98
146
using Base::operator ();
99
147
};
100
148
149
+ // / Trait to detect if T is a class or an union
101
150
template <typename T>
102
151
struct is_class_or_union
103
152
: std::integral_constant<bool , std::is_class<T>::value ||
104
153
std::is_union<T>::value> {};
154
+
155
+ // / Trait to remove cvref and call is_class_or_union
105
156
template <typename T>
106
157
struct is_class_or_union_remove_cvref
107
158
: is_class_or_union<typename std::remove_cv<
@@ -110,7 +161,7 @@ struct is_class_or_union_remove_cvref
110
161
// / Convert {boost,std}::variant<class...> alternative reference to a Python
111
162
// / object. This converter return the alternative reference. The code that
112
163
// / create the reference holder is taken from \see
113
- // / boost::python ::to_python_indirect.
164
+ // / bp ::to_python_indirect.
114
165
template <typename Variant>
115
166
struct VariantRefToObject : VariantVisitorType<PyObject*, Variant> {
116
167
typedef VariantVisitorType<PyObject*, Variant> Base;
@@ -125,22 +176,22 @@ struct VariantRefToObject : VariantVisitorType<PyObject*, Variant> {
125
176
typename std::enable_if<!is_class_or_union_remove_cvref<T>::value,
126
177
bool >::type = true >
127
178
result_type operator ()(T t) const {
128
- return boost::python:: incref (boost::python ::object (t).ptr ());
179
+ return bp:: incref (bp ::object (t).ptr ());
129
180
}
130
181
131
182
template <typename T,
132
183
typename std::enable_if<is_class_or_union_remove_cvref<T>::value,
133
184
bool >::type = true >
134
185
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);
136
187
}
137
188
138
189
// / Copy the object when it's None
139
190
using Base::operator ();
140
191
};
141
192
142
193
// / 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.
144
195
// / It will call \see VariantRefToObject to extract the alternative
145
196
// / reference.
146
197
template <typename Variant>
@@ -156,8 +207,7 @@ struct VariantConverter {
156
207
157
208
#ifndef BOOST_PYTHON_NO_PY_SIGNATURES
158
209
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 ();
161
211
}
162
212
#endif
163
213
};
@@ -169,19 +219,26 @@ template <typename Variant>
169
219
struct VariantImplicitlyConvertible {
170
220
typedef Variant variant_type;
171
221
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 >
173
230
void operator ()(T) {
174
- boost::python ::implicitly_convertible<T, variant_type>();
231
+ bp ::implicitly_convertible<T, variant_type>();
175
232
}
176
233
};
177
234
178
235
} // namespace details
179
236
180
- // / Variant of \see boost::python ::return_internal_reference that
237
+ // / Variant of \see bp ::return_internal_reference that
181
238
// / extract {boost,std}::variant<class...> alternative reference before
182
239
// / converting it into a PyObject
183
240
template <typename Variant>
184
- struct ReturnInternalVariant : boost::python ::return_internal_reference<> {
241
+ struct ReturnInternalVariant : bp ::return_internal_reference<> {
185
242
typedef Variant variant_type;
186
243
187
244
typedef details::VariantConverter<variant_type> result_converter;
@@ -192,7 +249,7 @@ struct ReturnInternalVariant : boost::python::return_internal_reference<> {
192
249
if (PyLong_Check (result) || PyBool_Check (result) || PyFloat_Check (result)) {
193
250
return result;
194
251
}
195
- return boost::python ::return_internal_reference<>::postcall (args_, result);
252
+ return bp ::return_internal_reference<>::postcall (args_, result);
196
253
}
197
254
};
198
255
@@ -208,12 +265,12 @@ struct ReturnInternalVariant : boost::python::return_internal_reference<> {
208
265
// / };
209
266
// / ...
210
267
// / 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<>())
213
270
// / typedef eigenpy::VariantConverter<MyVariant> Converter;
214
271
// / Converter::registration();
215
272
// /
216
- // / boost::python ::class_<VariantHolder>("VariantHolder", bp::init<>())
273
+ // / bp ::class_<VariantHolder>("VariantHolder", bp::init<>())
217
274
// / .add_property("variant",
218
275
// / bp::make_getter(&VariantHolder::variant,
219
276
// / Converter::return_internal_reference()),
@@ -228,7 +285,7 @@ struct VariantConverter {
228
285
typedef details::VariantValueToObject<variant_type> variant_to_value;
229
286
typedef typename details::VariantAlternatives<variant_type>::types types;
230
287
231
- boost::python ::to_python_converter<variant_type, variant_to_value>();
288
+ bp ::to_python_converter<variant_type, variant_to_value>();
232
289
boost::mpl::for_each<types>(
233
290
details::VariantImplicitlyConvertible<variant_type>());
234
291
}
0 commit comments