variant.hpp
Go to the documentation of this file.
1 //
2 // Copyright (c) 2024 INRIA
3 //
4 
5 #ifndef __eigenpy_utils_variant_hpp__
6 #define __eigenpy_utils_variant_hpp__
7 
8 #include "eigenpy/fwd.hpp"
11 
12 #include <boost/python.hpp>
13 #include <boost/variant.hpp>
14 #include <boost/mpl/for_each.hpp>
15 #include <boost/mpl/vector.hpp>
16 
17 #include <type_traits>
18 
19 #ifdef EIGENPY_WITH_CXX17_SUPPORT
20 #include <variant>
21 #endif
22 
23 namespace eigenpy {
24 
25 namespace details {
26 
28 template <typename ResultType, typename Variant>
30 
32 template <typename Variant>
34 
35 template <typename Variant>
36 struct empty_variant {};
37 
38 template <typename T>
39 struct is_empty_variant : std::false_type {};
40 
41 #ifdef EIGENPY_WITH_CXX17_SUPPORT
42 
44 template <typename ResultType, typename... Alternatives>
45 struct VariantVisitorType<ResultType, std::variant<Alternatives...> > {
46  typedef std::variant<Alternatives...> variant_type;
47  typedef ResultType result_type;
48 
49  template <typename Visitor, typename Visitable>
50  static result_type visit(Visitor&& visitor, Visitable&& v) {
51  return std::visit(std::forward<Visitor>(visitor),
52  std::forward<Visitable>(v));
53  }
54 
55  result_type operator()(std::monostate) const {
56  return bp::incref(bp::object().ptr()); // None
57  }
58 };
59 
60 template <typename... Alternatives>
61 struct VariantAlternatives<std::variant<Alternatives...> > {
62  typedef boost::mpl::vector<Alternatives...> types;
63 };
64 
65 template <typename... Alternatives>
66 struct empty_variant<std::variant<Alternatives...> > {
67  typedef std::monostate type;
68 };
69 
70 template <>
71 struct is_empty_variant<std::monostate> : std::true_type {};
72 
73 #endif
74 
76 template <typename ResultType, typename... Alternatives>
77 struct VariantVisitorType<ResultType, boost::variant<Alternatives...> >
78  : boost::static_visitor<ResultType> {
79  typedef boost::variant<Alternatives...> variant_type;
80  typedef ResultType result_type;
81 
82  template <typename Visitor, typename Visitable>
83  static result_type visit(Visitor&& visitor, Visitable&& visitable) {
84  return std::forward<Visitable>(visitable).apply_visitor(visitor);
85  }
86 
87  result_type operator()(boost::blank) const {
88  return bp::incref(bp::object().ptr()); // None
89  }
90 };
91 
92 template <typename... Alternatives>
93 struct VariantAlternatives<boost::variant<Alternatives...> > {
94  typedef typename boost::variant<Alternatives...>::types types;
95 };
96 
97 template <typename... Alternatives>
98 struct empty_variant<boost::variant<Alternatives...> > {
99  typedef boost::blank type;
100 };
101 
102 template <>
103 struct is_empty_variant<boost::blank> : std::true_type {};
104 
107 template <typename Variant>
109  static void registration() {
110  bp::converter::registry::push_back(convertible, construct,
111  bp::type_id<Variant>());
112  }
113 
114  // convertible only for None
115  static void* convertible(PyObject* obj) {
116  return (obj == Py_None) ? obj : nullptr;
117  };
118 
119  // construct in place
120  static void construct(PyObject*,
121  bp::converter::rvalue_from_python_stage1_data* data) {
122  void* storage =
123  reinterpret_cast<bp::converter::rvalue_from_python_storage<Variant>*>(
124  data)
125  ->storage.bytes;
126  new (storage) Variant(typename empty_variant<Variant>::type());
127  data->convertible = storage;
128  };
129 };
130 
132 template <typename T, class Enable = void>
134 
135 template <typename T>
137  T, typename std::enable_if<std::is_same<T, bool>::value>::type> {
138  static void* convertible(PyObject* obj) {
139  return PyBool_Check(obj) ? obj : nullptr;
140  }
141 
142  static PyTypeObject const* expected_pytype() { return &PyBool_Type; }
143 };
144 
145 template <typename T>
147  T, typename std::enable_if<!std::is_same<T, bool>::value &&
148  std::is_integral<T>::value>::type> {
149  static void* convertible(PyObject* obj) {
150  // PyLong return true for bool type
151  return (PyInt_Check(obj) && !PyBool_Check(obj)) ? obj : nullptr;
152  }
153 
154  static PyTypeObject const* expected_pytype() { return &PyLong_Type; }
155 };
156 
157 template <typename T>
159  T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
160  static void* convertible(PyObject* obj) {
161  return PyFloat_Check(obj) ? obj : nullptr;
162  }
163 
164  static PyTypeObject const* expected_pytype() { return &PyFloat_Type; }
165 };
166 
168 template <typename T, typename Variant>
170  static void registration() {
171  bp::converter::registry::push_back(
172  &convertible, &bp::converter::implicit<T, Variant>::construct,
173  bp::type_id<Variant>()
174 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
175  ,
177 #endif
178  );
179  }
180 
181  static void* convertible(PyObject* obj) {
183  }
184  static PyTypeObject const* expected_pytype() {
186  }
187 };
188 
191 template <typename Variant>
192 struct VariantValueToObject : VariantVisitorType<PyObject*, Variant> {
194  typedef typename Base::result_type result_type;
195  typedef typename Base::variant_type variant_type;
196 
198  return Base::visit(VariantValueToObject(), v);
199  }
200 
201  template <typename T>
203  return bp::incref(bp::object(t).ptr());
204  }
205 
206  using Base::operator();
207 };
208 
213 template <typename Variant>
214 struct VariantRefToObject : VariantVisitorType<PyObject*, Variant> {
216  typedef typename Base::result_type result_type;
217  typedef typename Base::variant_type variant_type;
218 
220  return Base::visit(VariantRefToObject(), v);
221  }
222 
223  template <typename T,
225  bool>::type = true>
227  return bp::incref(bp::object(t).ptr());
228  }
229 
230  template <typename T,
232  bool>::type = true>
234  return bp::detail::make_reference_holder::execute(&t);
235  }
236 
238  using Base::operator();
239 };
240 
245 template <typename Variant>
247  typedef Variant variant_type;
248 
249  template <class T>
250  struct apply {
251  struct type {
252  PyObject* operator()(const variant_type& v) const {
254  }
255 
256 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
257  PyTypeObject const* get_pytype() const {
258  return bp::converter::registered_pytype<variant_type>::get_pytype();
259  }
260 #endif
261  };
262  };
263 };
264 
266 template <typename Variant>
268  typedef Variant variant_type;
269 
271  bool>::type = true>
272  void operator()(T) {
274  }
275 
278  bool>::type = true>
279  void operator()(T) {
281  }
282 
285  bool>::type = true>
286  void operator()(T) {
287  bp::implicitly_convertible<T, variant_type>();
288  }
289 };
290 
291 } // namespace details
292 
296 template <typename Variant>
297 struct ReturnInternalVariant : bp::return_internal_reference<> {
298  typedef Variant variant_type;
299 
301 
302  template <class ArgumentPackage>
303  static PyObject* postcall(ArgumentPackage const& args_, PyObject* result) {
304  // Don't run return_internal_reference postcall on primitive type
305  if (PyInt_Check(result) || PyBool_Check(result) || PyFloat_Check(result) ||
306  PyStr_Check(result) || PyComplex_Check(result)) {
307  return result;
308  }
309  return bp::return_internal_reference<>::postcall(args_, result);
310  }
311 };
312 
336 template <typename Variant>
338  typedef Variant variant_type;
340 
341  static void registration() {
342  typedef details::VariantValueToObject<variant_type> variant_to_value;
344 
345  bp::to_python_converter<variant_type, variant_to_value>();
346  boost::mpl::for_each<types>(details::VariantConvertible<variant_type>());
347  }
348 };
349 
350 } // namespace eigenpy
351 
352 #endif // ifndef __eigenpy_utils_variant_hpp__
eigenpy::ReturnInternalVariant::postcall
static PyObject * postcall(ArgumentPackage const &args_, PyObject *result)
Definition: variant.hpp:303
eigenpy::details::NumericConvertibleImpl< T, typename std::enable_if< std::is_floating_point< T >::value >::type >::expected_pytype
static PyTypeObject const * expected_pytype()
Definition: variant.hpp:164
eigenpy::details::VariantVisitorType
Allow to use std::variant and boost::variant with the same API.
Definition: variant.hpp:29
eigenpy::details::VariantConverter::apply
Definition: variant.hpp:250
eigenpy::details::EmptyConvertible::convertible
static void * convertible(PyObject *obj)
Definition: variant.hpp:115
eigenpy::details::VariantValueToObject::operator()
result_type operator()(T &t) const
Definition: variant.hpp:202
eigenpy::VariantConverter
Definition: variant.hpp:337
eigenpy::details::VariantRefToObject::Base
VariantVisitorType< PyObject *, Variant > Base
Definition: variant.hpp:215
PyStr_Check
#define PyStr_Check
Definition: python-compat.hpp:18
eigenpy::details::VariantVisitorType< ResultType, boost::variant< Alternatives... > >::variant_type
boost::variant< Alternatives... > variant_type
Definition: variant.hpp:79
fwd.hpp
eigenpy::details::empty_variant< boost::variant< Alternatives... > >::type
boost::blank type
Definition: variant.hpp:99
setup.data
data
Definition: setup.in.py:48
eigenpy::details::VariantVisitorType< ResultType, boost::variant< Alternatives... > >::result_type
ResultType result_type
Definition: variant.hpp:80
eigenpy::details::EmptyConvertible
Definition: variant.hpp:108
eigenpy::details::VariantRefToObject::operator()
result_type operator()(T t) const
Definition: variant.hpp:226
eigenpy::details::VariantValueToObject::result_type
Base::result_type result_type
Definition: variant.hpp:194
boost
Definition: alignment.hpp:48
eigenpy::VariantConverter::registration
static void registration()
Definition: variant.hpp:341
eigenpy::VariantConverter::variant_type
Variant variant_type
Definition: variant.hpp:338
eigenpy::details::NumericConvertible::convertible
static void * convertible(PyObject *obj)
Definition: variant.hpp:181
eigenpy::details::VariantValueToObject::convert
static result_type convert(const variant_type &v)
Definition: variant.hpp:197
eigenpy::ReturnInternalVariant
Definition: variant.hpp:297
eigenpy::details::VariantConvertible::operator()
void operator()(T)
Definition: variant.hpp:272
eigenpy
Definition: alignment.hpp:14
eigenpy::details::VariantRefToObject::result_type
Base::result_type result_type
Definition: variant.hpp:216
eigenpy::details::VariantRefToObject::variant_type
Base::variant_type variant_type
Definition: variant.hpp:217
eigenpy::ReturnInternalVariant::result_converter
details::VariantConverter< variant_type > result_converter
Definition: variant.hpp:300
eigenpy::details::NumericConvertible::expected_pytype
static PyTypeObject const * expected_pytype()
Definition: variant.hpp:184
eigenpy::details::VariantConvertible
Convert an Alternative type to a Variant.
Definition: variant.hpp:267
eigenpy::details::NumericConvertibleImpl< T, typename std::enable_if< std::is_floating_point< T >::value >::type >::convertible
static void * convertible(PyObject *obj)
Definition: variant.hpp:160
eigenpy::details::VariantConverter::apply::type
Definition: variant.hpp:251
eigenpy::VariantConverter::return_internal_reference
ReturnInternalVariant< variant_type > return_internal_reference
Definition: variant.hpp:339
eigenpy::details::NumericConvertibleImpl< T, typename std::enable_if< std::is_same< T, bool >::value >::type >::convertible
static void * convertible(PyObject *obj)
Definition: variant.hpp:138
eigenpy::details::empty_variant
Definition: variant.hpp:36
eigenpy::details::VariantConverter::apply::type::operator()
PyObject * operator()(const variant_type &v) const
Definition: variant.hpp:252
eigenpy::details::VariantConvertible::variant_type
Variant variant_type
Definition: variant.hpp:268
eigenpy::details::VariantConverter
Definition: variant.hpp:246
eigenpy::details::is_empty_variant
Definition: variant.hpp:39
eigenpy::details::VariantValueToObject::variant_type
Base::variant_type variant_type
Definition: variant.hpp:195
python-compat.hpp
eigenpy::details::VariantAlternatives
Allow to get all alternatives in a boost::mpl vector.
Definition: variant.hpp:33
test_matrix.value
float value
Definition: test_matrix.py:161
eigenpy::details::VariantConverter::variant_type
Variant variant_type
Definition: variant.hpp:247
eigenpy::details::EmptyConvertible::registration
static void registration()
Definition: variant.hpp:109
test_std_pair.t
tuple t
Definition: test_std_pair.py:3
eigenpy::details::NumericConvertible
Convert numeric type to Variant without ambiguity.
Definition: variant.hpp:169
eigenpy::details::NumericConvertibleImpl< T, typename std::enable_if<!std::is_same< T, bool >::value &&std::is_integral< T >::value >::type >::expected_pytype
static PyTypeObject const * expected_pytype()
Definition: variant.hpp:154
eigenpy::details::NumericConvertibleImpl< T, typename std::enable_if< std::is_same< T, bool >::value >::type >::expected_pytype
static PyTypeObject const * expected_pytype()
Definition: variant.hpp:142
eigenpy::details::VariantVisitorType< ResultType, boost::variant< Alternatives... > >::operator()
result_type operator()(boost::blank) const
Definition: variant.hpp:87
eigenpy::ReturnInternalVariant::variant_type
Variant variant_type
Definition: variant.hpp:298
eigenpy::details::VariantRefToObject::convert
static result_type convert(const variant_type &v)
Definition: variant.hpp:219
eigenpy::details::VariantValueToObject::Base
VariantVisitorType< PyObject *, Variant > Base
Definition: variant.hpp:193
eigenpy::details::VariantConverter::apply::type::get_pytype
PyTypeObject const * get_pytype() const
Definition: variant.hpp:257
eigenpy::details::NumericConvertible::registration
static void registration()
Definition: variant.hpp:170
test_geometry.v
v
Definition: test_geometry.py:32
eigenpy::details::VariantAlternatives< boost::variant< Alternatives... > >::types
boost::variant< Alternatives... >::types types
Definition: variant.hpp:94
eigenpy::details::VariantRefToObject::operator()
result_type operator()(T &t) const
Definition: variant.hpp:233
eigenpy::details::EmptyConvertible::construct
static void construct(PyObject *, bp::converter::rvalue_from_python_stage1_data *data)
Definition: variant.hpp:120
eigenpy::details::NumericConvertibleImpl
Implement convertible and expected_pytype for bool, integer and float.
Definition: variant.hpp:133
eigenpy::details::VariantVisitorType< ResultType, boost::variant< Alternatives... > >::visit
static result_type visit(Visitor &&visitor, Visitable &&visitable)
Definition: variant.hpp:83
traits.hpp
eigenpy::details::NumericConvertibleImpl< T, typename std::enable_if<!std::is_same< T, bool >::value &&std::is_integral< T >::value >::type >::convertible
static void * convertible(PyObject *obj)
Definition: variant.hpp:149
eigenpy::details::VariantRefToObject
Definition: variant.hpp:214
eigenpy::details::VariantValueToObject
Definition: variant.hpp:192


eigenpy
Author(s): Justin Carpentier, Nicolas Mansard
autogenerated on Fri Jun 14 2024 02:15:58