2#include "proxsuite-nlp/python/fwd.hpp" 
    3#include "proxsuite-nlp/third-party/polymorphic_cxx14.hpp" 
    6#include <eigenpy/utils/traits.hpp> 
    8#include <boost/core/demangle.hpp> 
   14namespace boost::python {
 
   15template <
class T, 
class A> 
struct pointee<xyz::polymorphic<T, A>> {
 
   20namespace proxsuite::nlp {
 
   26  using X = 
typename bp::pointee<Poly>::type;
 
   27  bp::objects::class_value_wrapper<
 
   28      Poly, bp::objects::make_ptr_instance<
 
   29                X, bp::objects::pointer_holder<Poly, X>>>();
 
 
   73template <
class Base, 
class A>
 
   75    : bp::def_visitor<PolymorphicVisitor<xyz::polymorphic<Base, A>>> {
 
   76  using Poly = xyz::polymorphic<Base, A>;
 
   77  static_assert(std::is_polymorphic_v<Base>, 
"Type should be polymorphic!");
 
   79  template <
class PyClass> 
void visit(PyClass &cl)
 const {
 
   80    using T = 
typename PyClass::wrapped_type;
 
   81    using meta = 
typename PyClass::metadata;
 
   82    using held = 
typename meta::held_type;
 
   83    typedef bp::converter::implicit<held, Poly> functions;
 
   86    PROXSUITE_NLP_COMPILER_DIAGNOSTIC_IGNORED_DELETE_NON_ABSTRACT_NON_VIRTUAL_DTOR
 
   87    bp::converter::registry::insert(
 
   88        &functions::convertible, &functions::construct, bp::type_id<Poly>(),
 
   89        &bp::converter::expected_from_python_type_direct<T>::get_pytype);
 
   90    PROXSUITE_NLP_COMPILER_DIAGNOSTIC_POP
 
   97    if constexpr (std::is_base_of_v<boost::python::wrapper<Base>,
 
   98                                    typename PyClass::wrapped_type>) {
 
   99      cl.enable_pickling_(
true);
 
  107template <
typename Value>
 
  108struct OwningNonOwningHolder : boost::python::instance_holder {
 
  109  typedef Value held_type;
 
  110  typedef Value value_type;
 
  114    Value *operator()(Value &v) { 
return &v; };
 
  115    Value *operator()(Value *v) { 
return v; };
 
  118  Value *get_ptr() { 
return std::visit(PtrGetter(), m_held); }
 
  121  template <
typename... Args>
 
  122  OwningNonOwningHolder(PyObject *self, Args... args)
 
  123      : m_held(Value(boost::python::objects::do_unforward(
 
  124            std::forward<Args>(args), 0)...)) {
 
  125    boost::python::detail::initialize_wrapper(self, get_ptr());
 
  129  void *holds(boost::python::type_info dst_t, 
bool) {
 
  130    if (
void *wrapped = holds_wrapped(dst_t, get_ptr(), get_ptr()))
 
  133    boost::python::type_info src_t = boost::python::type_id<Value>();
 
  134    return src_t == dst_t ? get_ptr()
 
  135                          : boost::python::objects::find_static_type(
 
  136                                get_ptr(), src_t, dst_t);
 
  140  inline void *holds_wrapped(boost::python::type_info dst_t,
 
  141                             boost::python::wrapper<T> *, 
T *p) {
 
  142    return boost::python::type_id<T>() == dst_t ? p : 0;
 
  145  inline void *holds_wrapped(boost::python::type_info, ...) { 
return 0; }
 
  148  std::variant<Value, Value *> m_held;
 
 
  175template <
typename _PyBase, 
typename _Base>
 
  176struct PolymorphicWrapper : boost::python::wrapper<_Base> {
 
  177  using PyBase = _PyBase;
 
  180  PolymorphicWrapper() = 
default;
 
  181  PolymorphicWrapper(
const PolymorphicWrapper &o) : bp::wrapper<Base>(o) {
 
  184  PolymorphicWrapper(PolymorphicWrapper &&o) = 
default;
 
  186  PolymorphicWrapper &operator=(
const PolymorphicWrapper &o) {
 
  190    bp::wrapper<Base>::operator=(o);
 
  194  PolymorphicWrapper &operator=(PolymorphicWrapper &&o) = 
default;
 
  197  void deepcopy_owner() {
 
  198    namespace bp = boost::python;
 
  199    if (PyObject *owner_ptr = bp::detail::wrapper_base_::get_owner(*
this)) {
 
  200      bp::object copy = bp::import(
"copy");
 
  201      bp::object deepcopy = copy.attr(
"deepcopy");
 
  206      bp::object owner{bp::handle<>(bp::borrowed(owner_ptr))};
 
  212      copied_owner = deepcopy(owner);
 
  213      PyObject *copied_owner_ptr = copied_owner.ptr();
 
  222      bp::objects::instance<> *inst =
 
  223          ((bp::objects::instance<> *)copied_owner_ptr);
 
  227        std::ostringstream error_msg;
 
  228        error_msg << 
"OwningNonOwningHolder should be setup for " 
  229                  << boost::core::demangle(
typeid(PyBase).name()) << 
" type" 
  231        throw std::logic_error(error_msg.str());
 
  233      value_holder->m_held = 
static_cast<PyBase *
>(
this);
 
  235      bp::detail::initialize_wrapper(copied_owner_ptr, 
this);
 
  240  bp::object copied_owner;
 
 
  250template <
class poly_ref, 
class MakeHolder> 
struct ToPythonIndirectPoly {
 
  251  using poly_type = boost::remove_cv_ref_t<poly_ref>;
 
  253  template <
class U> PyObject *operator()(U 
const &x)
 const {
 
  254    return execute(
const_cast<U &
>(x));
 
  256#ifndef BOOST_PYTHON_NO_PY_SIGNATURES 
  257  PyTypeObject 
const *get_pytype() {
 
  258    return boost::python::converter::registered_pytype<poly_type>::get_pytype();
 
  263  template <
class T, 
class A>
 
  264  static PyObject *execute(
const xyz::polymorphic<T, A> &p) {
 
  265    if (p.valueless_after_move())
 
  266      return bp::detail::none();
 
  267    T *q = 
const_cast<T *
>(boost::get_pointer(p));
 
  269    return bp::to_python_indirect<const T &, MakeHolder>{}(q);
 
  280template <
class T, 
class A, 
class MakeHolder>
 
  281struct to_python_indirect<xyz::polymorphic<T, A> &, MakeHolder>
 
  282    : proxsuite::nlp::python::internal::ToPythonIndirectPoly<
 
  283          xyz::polymorphic<T, A> &, MakeHolder> {};
 
  285template <
class T, 
class A, 
class MakeHolder>
 
  286struct to_python_indirect<const xyz::polymorphic<T, A> &, MakeHolder>
 
  287    : proxsuite::nlp::python::internal::ToPythonIndirectPoly<
 
  288          const xyz::polymorphic<T, A> &, MakeHolder> {};
 
#define PROXSUITE_NLP_COMPILER_DIAGNOSTIC_PUSH
macros for pragma push/pop/ignore deprecated warnings
 
void register_polymorphic_to_python()
Expose a polymorphic value type, e.g. xyz::polymorphic<T, A>.