Program Listing for File optional.hpp
↰ Return to documentation for file (include/eigenpy/optional.hpp
)
#ifndef __eigenpy_optional_hpp__
#define __eigenpy_optional_hpp__
#include "eigenpy/fwd.hpp"
#include "eigenpy/eigen-from-python.hpp"
#include "eigenpy/registration.hpp"
#include <boost/optional.hpp>
#ifdef EIGENPY_WITH_CXX17_SUPPORT
#include <optional>
#endif
#ifndef EIGENPY_DEFAULT_OPTIONAL
#define EIGENPY_DEFAULT_OPTIONAL boost::optional
#endif
namespace boost {
namespace python {
namespace converter {
template <typename T>
struct expected_pytype_for_arg<boost::optional<T> >
: expected_pytype_for_arg<T> {};
#ifdef EIGENPY_WITH_CXX17_SUPPORT
template <typename T>
struct expected_pytype_for_arg<std::optional<T> > : expected_pytype_for_arg<T> {
};
#endif
} // namespace converter
} // namespace python
} // namespace boost
namespace eigenpy {
namespace detail {
template <template <typename> class OptionalTpl>
struct nullopt_helper {};
template <>
struct nullopt_helper<boost::optional> {
typedef boost::none_t type;
static type value() { return boost::none; }
};
#ifdef EIGENPY_WITH_CXX17_SUPPORT
template <>
struct nullopt_helper<std::optional> {
typedef std::nullopt_t type;
static type value() { return std::nullopt; }
};
#endif
template <typename NoneType>
struct NoneToPython {
static PyObject *convert(const NoneType &) { Py_RETURN_NONE; }
static void registration() {
if (!check_registration<NoneType>()) {
bp::to_python_converter<NoneType, NoneToPython, false>();
}
}
};
template <typename T,
template <typename> class OptionalTpl = EIGENPY_DEFAULT_OPTIONAL>
struct OptionalToPython {
static PyObject *convert(const OptionalTpl<T> &obj) {
if (obj)
return bp::incref(bp::object(*obj).ptr());
else {
return bp::incref(bp::object().ptr()); // None
}
}
static PyTypeObject const *get_pytype() {
return bp::converter::registered_pytype<T>::get_pytype();
}
static void registration() {
if (!check_registration<OptionalTpl<T> >()) {
bp::to_python_converter<OptionalTpl<T>, OptionalToPython, true>();
}
}
};
template <typename T,
template <typename> class OptionalTpl = EIGENPY_DEFAULT_OPTIONAL>
struct OptionalFromPython {
static void *convertible(PyObject *obj_ptr);
static void construct(PyObject *obj_ptr,
bp::converter::rvalue_from_python_stage1_data *memory);
static void registration();
};
template <typename T, template <typename> class OptionalTpl>
void *OptionalFromPython<T, OptionalTpl>::convertible(PyObject *obj_ptr) {
if (obj_ptr == Py_None) {
return obj_ptr;
}
bp::extract<T> bp_obj(obj_ptr);
if (!bp_obj.check())
return 0;
else
return obj_ptr;
}
template <typename T, template <typename> class OptionalTpl>
void OptionalFromPython<T, OptionalTpl>::construct(
PyObject *obj_ptr, bp::converter::rvalue_from_python_stage1_data *memory) {
// create storage
using rvalue_storage_t =
bp::converter::rvalue_from_python_storage<OptionalTpl<T> >;
void *storage =
reinterpret_cast<rvalue_storage_t *>(reinterpret_cast<void *>(memory))
->storage.bytes;
if (obj_ptr == Py_None) {
new (storage) OptionalTpl<T>(nullopt_helper<OptionalTpl>::value());
} else {
const T value = bp::extract<T>(obj_ptr);
new (storage) OptionalTpl<T>(value);
}
memory->convertible = storage;
}
template <typename T, template <typename> class OptionalTpl>
void OptionalFromPython<T, OptionalTpl>::registration() {
bp::converter::registry::push_back(
&convertible, &construct, bp::type_id<OptionalTpl<T> >(),
bp::converter::expected_pytype_for_arg<OptionalTpl<T> >::get_pytype);
}
} // namespace detail
template <typename T,
template <typename> class OptionalTpl = EIGENPY_DEFAULT_OPTIONAL>
struct OptionalConverter {
static void registration() {
detail::OptionalToPython<T, OptionalTpl>::registration();
detail::OptionalFromPython<T, OptionalTpl>::registration();
}
};
} // namespace eigenpy
#endif // __eigenpy_optional_hpp__