.. _program_listing_file__tmp_ws_src_eigenpy_include_eigenpy_variant.hpp: Program Listing for File variant.hpp ==================================== |exhale_lsh| :ref:`Return to documentation for file ` (``/tmp/ws/src/eigenpy/include/eigenpy/variant.hpp``) .. |exhale_lsh| unicode:: U+021B0 .. UPWARDS ARROW WITH TIP LEFTWARDS .. code-block:: cpp // // Copyright (c) 2024 INRIA // #ifndef __eigenpy_utils_variant_hpp__ #define __eigenpy_utils_variant_hpp__ #include "eigenpy/fwd.hpp" #include "eigenpy/utils/traits.hpp" #include "eigenpy/utils/python-compat.hpp" #include #include #include #include #include #ifdef EIGENPY_WITH_CXX17_SUPPORT #include #endif namespace eigenpy { namespace details { template struct VariantVisitorType {}; template struct VariantAlternatives {}; template struct empty_variant {}; template struct is_empty_variant : std::false_type {}; #ifdef EIGENPY_WITH_CXX17_SUPPORT template struct VariantVisitorType > { typedef std::variant variant_type; typedef ResultType result_type; template static result_type visit(Visitor&& visitor, Visitable&& v) { return std::visit(std::forward(visitor), std::forward(v)); } result_type operator()(std::monostate) const { return bp::incref(bp::object().ptr()); // None } }; template struct VariantAlternatives > { typedef boost::mpl::vector types; }; template struct empty_variant > { typedef std::monostate type; }; template <> struct is_empty_variant : std::true_type {}; #endif template struct VariantVisitorType > : boost::static_visitor { typedef boost::variant variant_type; typedef ResultType result_type; template static result_type visit(Visitor&& visitor, Visitable&& visitable) { return std::forward(visitable).apply_visitor(visitor); } result_type operator()(boost::blank) const { return bp::incref(bp::object().ptr()); // None } }; template struct VariantAlternatives > { typedef typename boost::variant::types types; }; template struct empty_variant > { typedef boost::blank type; }; template <> struct is_empty_variant : std::true_type {}; template struct EmptyConvertible { static void registration() { bp::converter::registry::push_back(convertible, construct, bp::type_id()); } // convertible only for None static void* convertible(PyObject* obj) { return (obj == Py_None) ? obj : nullptr; }; // construct in place static void construct(PyObject*, bp::converter::rvalue_from_python_stage1_data* data) { void* storage = reinterpret_cast*>( data) ->storage.bytes; new (storage) Variant(typename empty_variant::type()); data->convertible = storage; }; }; template struct NumericConvertibleImpl {}; template struct NumericConvertibleImpl< T, typename std::enable_if::value>::type> { static void* convertible(PyObject* obj) { return PyBool_Check(obj) ? obj : nullptr; } static PyTypeObject const* expected_pytype() { return &PyBool_Type; } }; template struct NumericConvertibleImpl< T, typename std::enable_if::value && std::is_integral::value>::type> { static void* convertible(PyObject* obj) { // PyLong return true for bool type return (PyInt_Check(obj) && !PyBool_Check(obj)) ? obj : nullptr; } static PyTypeObject const* expected_pytype() { return &PyLong_Type; } }; template struct NumericConvertibleImpl< T, typename std::enable_if::value>::type> { static void* convertible(PyObject* obj) { return PyFloat_Check(obj) ? obj : nullptr; } static PyTypeObject const* expected_pytype() { return &PyFloat_Type; } }; template struct NumericConvertible { static void registration() { bp::converter::registry::push_back( &convertible, &bp::converter::implicit::construct, bp::type_id() #ifndef BOOST_PYTHON_NO_PY_SIGNATURES , &expected_pytype #endif ); } static void* convertible(PyObject* obj) { return NumericConvertibleImpl::convertible(obj); } static PyTypeObject const* expected_pytype() { return NumericConvertibleImpl::expected_pytype(); } }; template struct VariantValueToObject : VariantVisitorType { typedef VariantVisitorType Base; typedef typename Base::result_type result_type; typedef typename Base::variant_type variant_type; static result_type convert(const variant_type& v) { return Base::visit(VariantValueToObject(), v); } template result_type operator()(T& t) const { return bp::incref(bp::object(t).ptr()); } using Base::operator(); }; template struct VariantRefToObject : VariantVisitorType { typedef VariantVisitorType Base; typedef typename Base::result_type result_type; typedef typename Base::variant_type variant_type; static result_type convert(const variant_type& v) { return Base::visit(VariantRefToObject(), v); } template ::value, bool>::type = true> result_type operator()(T t) const { return bp::incref(bp::object(t).ptr()); } template ::value, bool>::type = true> result_type operator()(T& t) const { return bp::detail::make_reference_holder::execute(&t); } using Base::operator(); }; template struct VariantConverter { typedef Variant variant_type; template struct apply { struct type { PyObject* operator()(const variant_type& v) const { return VariantRefToObject::convert(v); } #ifndef BOOST_PYTHON_NO_PY_SIGNATURES PyTypeObject const* get_pytype() const { return bp::converter::registered_pytype::get_pytype(); } #endif }; }; }; template struct VariantConvertible { typedef Variant variant_type; template ::value, bool>::type = true> void operator()(T) { EmptyConvertible::registration(); } template ::value && std::is_arithmetic::value, bool>::type = true> void operator()(T) { NumericConvertible::registration(); } template ::value && !std::is_arithmetic::value, bool>::type = true> void operator()(T) { bp::implicitly_convertible(); } }; } // namespace details template struct ReturnInternalVariant : bp::return_internal_reference<> { typedef Variant variant_type; typedef details::VariantConverter result_converter; template static PyObject* postcall(ArgumentPackage const& args_, PyObject* result) { // Don't run return_internal_reference postcall on primitive type if (PyInt_Check(result) || PyBool_Check(result) || PyFloat_Check(result) || PyStr_Check(result) || PyComplex_Check(result)) { return result; } return bp::return_internal_reference<>::postcall(args_, result); } }; template struct VariantConverter { typedef Variant variant_type; typedef ReturnInternalVariant return_internal_reference; static void registration() { typedef details::VariantValueToObject variant_to_value; typedef typename details::VariantAlternatives::types types; bp::to_python_converter(); boost::mpl::for_each(details::VariantConvertible()); } }; } // namespace eigenpy #endif // ifndef __eigenpy_utils_variant_hpp__