5 #ifndef __eigenpy_utils_variant_hpp__
6 #define __eigenpy_utils_variant_hpp__
12 #include <boost/python.hpp>
13 #include <boost/variant.hpp>
14 #include <boost/mpl/for_each.hpp>
15 #include <boost/mpl/vector.hpp>
17 #include <type_traits>
19 #ifdef EIGENPY_WITH_CXX17_SUPPORT
28 template <
typename ResultType,
typename Variant>
32 template <
typename Variant>
35 template <
typename Variant>
41 #ifdef EIGENPY_WITH_CXX17_SUPPORT
44 template <
typename ResultType,
typename... Alternatives>
46 typedef std::variant<Alternatives...> variant_type;
47 typedef ResultType result_type;
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));
55 result_type operator()(std::monostate)
const {
56 return bp::incref(bp::object().ptr());
60 template <
typename... Alternatives>
61 struct VariantAlternatives<std::variant<Alternatives...> > {
62 typedef boost::mpl::vector<Alternatives...> types;
65 template <
typename... Alternatives>
66 struct empty_variant<std::variant<Alternatives...> > {
67 typedef std::monostate type;
71 struct is_empty_variant<std::monostate> : std::true_type {};
76 template <
typename ResultType,
typename... Alternatives>
78 : boost::static_visitor<ResultType> {
82 template <
typename Visitor,
typename Visitable>
84 return std::forward<Visitable>(visitable).apply_visitor(visitor);
88 return bp::incref(bp::object().ptr());
92 template <
typename... Alternatives>
97 template <
typename... Alternatives>
107 template <
typename Variant>
111 bp::type_id<Variant>());
116 return (obj == Py_None) ? obj :
nullptr;
121 bp::converter::rvalue_from_python_stage1_data*
data) {
123 reinterpret_cast<bp::converter::rvalue_from_python_storage<Variant>*
>(
127 data->convertible = storage;
132 template <
typename T,
class Enable =
void>
135 template <
typename T>
137 T, typename std::enable_if<std::is_same<T, bool>::value>::type> {
139 return PyBool_Check(obj) ? obj :
nullptr;
145 template <
typename T>
147 T, typename std::enable_if<!std::is_same<T, bool>::value &&
148 std::is_integral<T>::value>::type> {
151 return (PyInt_Check(obj) && !PyBool_Check(obj)) ? obj :
nullptr;
157 template <
typename T>
159 T, typename std::enable_if<std::is_floating_point<T>::value>::type> {
161 return PyFloat_Check(obj) ? obj :
nullptr;
168 template <
typename T,
typename Variant>
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
191 template <
typename Variant>
201 template <
typename T>
203 return bp::incref(bp::object(
t).ptr());
206 using Base::operator();
213 template <
typename Variant>
223 template <
typename T,
227 return bp::incref(bp::object(
t).ptr());
230 template <
typename T,
234 return bp::detail::make_reference_holder::execute(&
t);
238 using Base::operator();
245 template <
typename Variant>
256 #ifndef BOOST_PYTHON_NO_PY_SIGNATURES
258 return bp::converter::registered_pytype<variant_type>::get_pytype();
266 template <
typename Variant>
287 bp::implicitly_convertible<T, variant_type>();
296 template <
typename Variant>
302 template <
class ArgumentPackage>
303 static PyObject*
postcall(ArgumentPackage
const& args_, PyObject* result) {
305 if (PyInt_Check(result) || PyBool_Check(result) || PyFloat_Check(result) ||
309 return bp::return_internal_reference<>::postcall(args_, result);
336 template <
typename Variant>
345 bp::to_python_converter<variant_type, variant_to_value>();
352 #endif // ifndef __eigenpy_utils_variant_hpp__