File indexing completed on 2026-05-06 08:48:35
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #pragma once
0011
0012 #include <pybind11/gil.h>
0013 #include <pybind11/pytypes.h>
0014 #include <pybind11/trampoline_self_life_support.h>
0015
0016 #include "common.h"
0017 #include "cpp_conduit.h"
0018 #include "descr.h"
0019 #include "dynamic_raw_ptr_cast_if_possible.h"
0020 #include "internals.h"
0021 #include "typeid.h"
0022 #include "using_smart_holder.h"
0023 #include "value_and_holder.h"
0024
0025 #include <cstdint>
0026 #include <cstring>
0027 #include <iterator>
0028 #include <new>
0029 #include <stdexcept>
0030 #include <string>
0031 #include <type_traits>
0032 #include <typeindex>
0033 #include <typeinfo>
0034 #include <unordered_map>
0035 #include <utility>
0036 #include <vector>
0037
0038 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0039 PYBIND11_NAMESPACE_BEGIN(detail)
0040
0041
0042
0043 class loader_life_support {
0044 private:
0045 loader_life_support *parent = nullptr;
0046 std::unordered_set<PyObject *> keep_alive;
0047
0048 public:
0049
0050 loader_life_support() {
0051 auto &stack_top = get_internals().loader_life_support_tls;
0052 parent = stack_top.get();
0053 stack_top = this;
0054 }
0055
0056
0057 ~loader_life_support() {
0058 auto &stack_top = get_internals().loader_life_support_tls;
0059 if (stack_top.get() != this) {
0060 pybind11_fail("loader_life_support: internal error");
0061 }
0062 stack_top = parent;
0063 for (auto *item : keep_alive) {
0064 Py_DECREF(item);
0065 }
0066 }
0067
0068
0069
0070 PYBIND11_NOINLINE static void add_patient(handle h) {
0071 loader_life_support *frame = get_internals().loader_life_support_tls.get();
0072 if (!frame) {
0073
0074
0075
0076
0077 throw cast_error("When called outside a bound function, py::cast() cannot "
0078 "do Python -> C++ conversions which require the creation "
0079 "of temporary values");
0080 }
0081
0082 if (frame->keep_alive.insert(h.ptr()).second) {
0083 Py_INCREF(h.ptr());
0084 }
0085 }
0086 };
0087
0088
0089
0090
0091 inline std::pair<decltype(internals::registered_types_py)::iterator, bool>
0092 all_type_info_get_cache(PyTypeObject *type);
0093
0094
0095 inline void all_type_info_add_base_most_derived_first(std::vector<type_info *> &bases,
0096 type_info *addl_base) {
0097 for (auto it = bases.begin(); it != bases.end(); it++) {
0098 type_info *existing_base = *it;
0099 if (PyType_IsSubtype(addl_base->type, existing_base->type) != 0) {
0100 bases.insert(it, addl_base);
0101 return;
0102 }
0103 }
0104 bases.push_back(addl_base);
0105 }
0106
0107
0108 PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_info *> &bases) {
0109 assert(bases.empty());
0110 std::vector<PyTypeObject *> check;
0111 for (handle parent : reinterpret_borrow<tuple>(t->tp_bases)) {
0112 check.push_back((PyTypeObject *) parent.ptr());
0113 }
0114 auto const &type_dict = get_internals().registered_types_py;
0115 for (size_t i = 0; i < check.size(); i++) {
0116 auto *type = check[i];
0117
0118 if (!PyType_Check((PyObject *) type)) {
0119 continue;
0120 }
0121
0122
0123 auto it = type_dict.find(type);
0124 if (it != type_dict.end()) {
0125
0126
0127
0128
0129 for (auto *tinfo : it->second) {
0130
0131
0132
0133 bool found = false;
0134 for (auto *known : bases) {
0135 if (known == tinfo) {
0136 found = true;
0137 break;
0138 }
0139 }
0140 if (!found) {
0141 all_type_info_add_base_most_derived_first(bases, tinfo);
0142 }
0143 }
0144 } else if (type->tp_bases) {
0145
0146
0147 if (i + 1 == check.size()) {
0148
0149
0150
0151 check.pop_back();
0152 i--;
0153 }
0154 for (handle parent : reinterpret_borrow<tuple>(type->tp_bases)) {
0155 check.push_back((PyTypeObject *) parent.ptr());
0156 }
0157 }
0158 }
0159 }
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169
0170
0171 inline const std::vector<detail::type_info *> &all_type_info(PyTypeObject *type) {
0172 return all_type_info_get_cache(type).first->second;
0173 }
0174
0175
0176
0177
0178
0179
0180 PYBIND11_NOINLINE detail::type_info *get_type_info(PyTypeObject *type) {
0181 const auto &bases = all_type_info(type);
0182 if (bases.empty()) {
0183 return nullptr;
0184 }
0185 if (bases.size() > 1) {
0186 pybind11_fail(
0187 "pybind11::detail::get_type_info: type has multiple pybind11-registered bases");
0188 }
0189 return bases.front();
0190 }
0191
0192 inline detail::type_info *get_local_type_info(const std::type_index &tp) {
0193 auto &locals = get_local_internals().registered_types_cpp;
0194 auto it = locals.find(tp);
0195 if (it != locals.end()) {
0196 return it->second;
0197 }
0198 return nullptr;
0199 }
0200
0201 inline detail::type_info *get_global_type_info(const std::type_index &tp) {
0202 return with_internals([&](internals &internals) {
0203 detail::type_info *type_info = nullptr;
0204 auto &types = internals.registered_types_cpp;
0205 auto it = types.find(tp);
0206 if (it != types.end()) {
0207 type_info = it->second;
0208 }
0209 return type_info;
0210 });
0211 }
0212
0213
0214
0215 PYBIND11_NOINLINE detail::type_info *get_type_info(const std::type_index &tp,
0216 bool throw_if_missing = false) {
0217 if (auto *ltype = get_local_type_info(tp)) {
0218 return ltype;
0219 }
0220 if (auto *gtype = get_global_type_info(tp)) {
0221 return gtype;
0222 }
0223
0224 if (throw_if_missing) {
0225 std::string tname = tp.name();
0226 detail::clean_type_id(tname);
0227 pybind11_fail("pybind11::detail::get_type_info: unable to find type info for \""
0228 + std::move(tname) + '"');
0229 }
0230 return nullptr;
0231 }
0232
0233 PYBIND11_NOINLINE handle get_type_handle(const std::type_info &tp, bool throw_if_missing) {
0234 detail::type_info *type_info = get_type_info(tp, throw_if_missing);
0235 return handle(type_info ? ((PyObject *) type_info->type) : nullptr);
0236 }
0237
0238 inline bool try_incref(PyObject *obj) {
0239
0240
0241
0242 #ifdef Py_GIL_DISABLED
0243
0244
0245 uint32_t local = _Py_atomic_load_uint32_relaxed(&obj->ob_ref_local);
0246 local += 1;
0247 if (local == 0) {
0248
0249 return true;
0250 }
0251 if (_Py_IsOwnedByCurrentThread(obj)) {
0252 _Py_atomic_store_uint32_relaxed(&obj->ob_ref_local, local);
0253 # ifdef Py_REF_DEBUG
0254 _Py_INCREF_IncRefTotal();
0255 # endif
0256 return true;
0257 }
0258 Py_ssize_t shared = _Py_atomic_load_ssize_relaxed(&obj->ob_ref_shared);
0259 for (;;) {
0260
0261
0262 if (shared == 0 || shared == _Py_REF_MERGED) {
0263 return false;
0264 }
0265
0266 if (_Py_atomic_compare_exchange_ssize(
0267 &obj->ob_ref_shared, &shared, shared + (1 << _Py_REF_SHARED_SHIFT))) {
0268 # ifdef Py_REF_DEBUG
0269 _Py_INCREF_IncRefTotal();
0270 # endif
0271 return true;
0272 }
0273 }
0274 #else
0275 assert(Py_REFCNT(obj) > 0);
0276 Py_INCREF(obj);
0277 return true;
0278 #endif
0279 }
0280
0281
0282 PYBIND11_NOINLINE handle find_registered_python_instance(void *src,
0283 const detail::type_info *tinfo) {
0284 return with_instance_map(src, [&](instance_map &instances) {
0285 auto it_instances = instances.equal_range(src);
0286 for (auto it_i = it_instances.first; it_i != it_instances.second; ++it_i) {
0287 for (auto *instance_type : detail::all_type_info(Py_TYPE(it_i->second))) {
0288 if (instance_type && same_type(*instance_type->cpptype, *tinfo->cpptype)) {
0289 auto *wrapper = reinterpret_cast<PyObject *>(it_i->second);
0290 if (try_incref(wrapper)) {
0291 return handle(wrapper);
0292 }
0293 }
0294 }
0295 }
0296 return handle();
0297 });
0298 }
0299
0300
0301 struct values_and_holders {
0302 private:
0303 instance *inst;
0304 using type_vec = std::vector<detail::type_info *>;
0305 const type_vec &tinfo;
0306
0307 public:
0308 explicit values_and_holders(instance *inst)
0309 : inst{inst}, tinfo(all_type_info(Py_TYPE(inst))) {}
0310
0311 explicit values_and_holders(PyObject *obj)
0312 : inst{nullptr}, tinfo(all_type_info(Py_TYPE(obj))) {
0313 if (!tinfo.empty()) {
0314 inst = reinterpret_cast<instance *>(obj);
0315 }
0316 }
0317
0318 struct iterator {
0319 private:
0320 instance *inst = nullptr;
0321 const type_vec *types = nullptr;
0322 value_and_holder curr;
0323 friend struct values_and_holders;
0324 iterator(instance *inst, const type_vec *tinfo) : inst{inst}, types{tinfo} {
0325 if (inst != nullptr) {
0326 assert(!types->empty());
0327 curr = value_and_holder(
0328 inst ,
0329 (*types)[0] ,
0330 0,
0331 0 );
0332 }
0333 }
0334
0335 explicit iterator(size_t end) : curr(end) {}
0336
0337 public:
0338 bool operator==(const iterator &other) const { return curr.index == other.curr.index; }
0339 bool operator!=(const iterator &other) const { return curr.index != other.curr.index; }
0340 iterator &operator++() {
0341 if (!inst->simple_layout) {
0342 curr.vh += 1 + (*types)[curr.index]->holder_size_in_ptrs;
0343 }
0344 ++curr.index;
0345 curr.type = curr.index < types->size() ? (*types)[curr.index] : nullptr;
0346 return *this;
0347 }
0348 value_and_holder &operator*() { return curr; }
0349 value_and_holder *operator->() { return &curr; }
0350 };
0351
0352 iterator begin() { return iterator(inst, &tinfo); }
0353 iterator end() { return iterator(tinfo.size()); }
0354
0355 iterator find(const type_info *find_type) {
0356 auto it = begin(), endit = end();
0357 while (it != endit && it->type != find_type) {
0358 ++it;
0359 }
0360 return it;
0361 }
0362
0363 size_t size() { return tinfo.size(); }
0364
0365
0366 bool is_redundant_value_and_holder(const value_and_holder &vh) {
0367 for (size_t i = 0; i < vh.index; i++) {
0368 if (PyType_IsSubtype(tinfo[i]->type, tinfo[vh.index]->type) != 0) {
0369 return true;
0370 }
0371 }
0372 return false;
0373 }
0374 };
0375
0376
0377
0378
0379
0380
0381
0382
0383
0384
0385
0386 PYBIND11_NOINLINE value_and_holder
0387 instance::get_value_and_holder(const type_info *find_type ,
0388 bool throw_if_missing ) {
0389
0390 if (!find_type || Py_TYPE(this) == find_type->type) {
0391 return value_and_holder(this, find_type, 0, 0);
0392 }
0393
0394 detail::values_and_holders vhs(this);
0395 auto it = vhs.find(find_type);
0396 if (it != vhs.end()) {
0397 return *it;
0398 }
0399
0400 if (!throw_if_missing) {
0401 return value_and_holder();
0402 }
0403
0404 #if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
0405 pybind11_fail("pybind11::detail::instance::get_value_and_holder: `"
0406 + get_fully_qualified_tp_name(find_type->type)
0407 + "' is not a pybind11 base of the given `"
0408 + get_fully_qualified_tp_name(Py_TYPE(this)) + "' instance");
0409 #else
0410 pybind11_fail(
0411 "pybind11::detail::instance::get_value_and_holder: "
0412 "type is not a pybind11 base of the given instance "
0413 "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for type details)");
0414 #endif
0415 }
0416
0417 PYBIND11_NOINLINE void instance::allocate_layout() {
0418 const auto &tinfo = all_type_info(Py_TYPE(this));
0419
0420 const size_t n_types = tinfo.size();
0421
0422 if (n_types == 0) {
0423 pybind11_fail(
0424 "instance allocation failed: new instance has no pybind11-registered base types");
0425 }
0426
0427 simple_layout
0428 = n_types == 1 && tinfo.front()->holder_size_in_ptrs <= instance_simple_holder_in_ptrs();
0429
0430
0431 if (simple_layout) {
0432 simple_value_holder[0] = nullptr;
0433 simple_holder_constructed = false;
0434 simple_instance_registered = false;
0435 } else {
0436
0437
0438
0439
0440 size_t space = 0;
0441 for (auto *t : tinfo) {
0442 space += 1;
0443 space += t->holder_size_in_ptrs;
0444 }
0445 size_t flags_at = space;
0446 space += size_in_ptrs(n_types);
0447
0448
0449
0450
0451
0452
0453
0454
0455 nonsimple.values_and_holders = (void **) PyMem_Calloc(space, sizeof(void *));
0456 if (!nonsimple.values_and_holders) {
0457 throw std::bad_alloc();
0458 }
0459 nonsimple.status
0460 = reinterpret_cast<std::uint8_t *>(&nonsimple.values_and_holders[flags_at]);
0461 }
0462 owned = true;
0463 }
0464
0465
0466 PYBIND11_NOINLINE void instance::deallocate_layout() {
0467 if (!simple_layout) {
0468 PyMem_Free(reinterpret_cast<void *>(nonsimple.values_and_holders));
0469 }
0470 }
0471
0472 PYBIND11_NOINLINE bool isinstance_generic(handle obj, const std::type_info &tp) {
0473 handle type = detail::get_type_handle(tp, false);
0474 if (!type) {
0475 return false;
0476 }
0477 return isinstance(obj, type);
0478 }
0479
0480 PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_info *type) {
0481 return with_instance_map(ptr, [&](instance_map &instances) {
0482 auto range = instances.equal_range(ptr);
0483 for (auto it = range.first; it != range.second; ++it) {
0484 for (const auto &vh : values_and_holders(it->second)) {
0485 if (vh.type == type) {
0486 return handle((PyObject *) it->second);
0487 }
0488 }
0489 }
0490 return handle();
0491 });
0492 }
0493
0494
0495 void keep_alive_impl(handle nurse, handle patient);
0496 inline PyObject *make_new_instance(PyTypeObject *type);
0497
0498 PYBIND11_WARNING_PUSH
0499 PYBIND11_WARNING_DISABLE_GCC("-Wredundant-decls")
0500
0501
0502 inline bool deregister_instance(instance *self, void *valptr, const type_info *tinfo);
0503
0504 PYBIND11_WARNING_POP
0505
0506 PYBIND11_NAMESPACE_BEGIN(smart_holder_type_caster_support)
0507
0508 struct value_and_holder_helper {
0509 value_and_holder loaded_v_h;
0510
0511 bool have_holder() const {
0512 return loaded_v_h.vh != nullptr && loaded_v_h.holder_constructed();
0513 }
0514
0515 smart_holder &holder() const { return loaded_v_h.holder<smart_holder>(); }
0516
0517 void throw_if_uninitialized_or_disowned_holder(const char *typeid_name) const {
0518 static const std::string missing_value_msg = "Missing value for wrapped C++ type `";
0519 if (!holder().is_populated) {
0520 throw value_error(missing_value_msg + clean_type_id(typeid_name)
0521 + "`: Python instance is uninitialized.");
0522 }
0523 if (!holder().has_pointee()) {
0524 throw value_error(missing_value_msg + clean_type_id(typeid_name)
0525 + "`: Python instance was disowned.");
0526 }
0527 }
0528
0529 void throw_if_uninitialized_or_disowned_holder(const std::type_info &type_info) const {
0530 throw_if_uninitialized_or_disowned_holder(type_info.name());
0531 }
0532
0533
0534 void throw_if_instance_is_currently_owned_by_shared_ptr(const type_info *tinfo) const {
0535 auto *vptr_gd_ptr = tinfo->get_memory_guarded_delete(holder().vptr);
0536 if (vptr_gd_ptr != nullptr && !vptr_gd_ptr->released_ptr.expired()) {
0537 throw value_error("Python instance is currently owned by a std::shared_ptr.");
0538 }
0539 }
0540
0541 void *get_void_ptr_or_nullptr() const {
0542 if (have_holder()) {
0543 auto &hld = holder();
0544 if (hld.is_populated && hld.has_pointee()) {
0545 return hld.template as_raw_ptr_unowned<void>();
0546 }
0547 }
0548 return nullptr;
0549 }
0550 };
0551
0552 template <typename T, typename D>
0553 handle smart_holder_from_unique_ptr(std::unique_ptr<T, D> &&src,
0554 return_value_policy policy,
0555 handle parent,
0556 const std::pair<const void *, const type_info *> &st) {
0557 if (policy == return_value_policy::copy) {
0558 throw cast_error("return_value_policy::copy is invalid for unique_ptr.");
0559 }
0560 if (!src) {
0561 return none().release();
0562 }
0563 void *src_raw_void_ptr = const_cast<void *>(st.first);
0564 assert(st.second != nullptr);
0565 const detail::type_info *tinfo = st.second;
0566 if (handle existing_inst = find_registered_python_instance(src_raw_void_ptr, tinfo)) {
0567 auto *self_life_support = tinfo->get_trampoline_self_life_support(src.get());
0568 if (self_life_support != nullptr) {
0569 value_and_holder &v_h = self_life_support->v_h;
0570 if (v_h.inst != nullptr && v_h.vh != nullptr) {
0571 auto &holder = v_h.holder<smart_holder>();
0572 if (!holder.is_disowned) {
0573 pybind11_fail("smart_holder_from_unique_ptr: unexpected "
0574 "smart_holder.is_disowned failure.");
0575 }
0576
0577 self_life_support->deactivate_life_support();
0578 holder.reclaim_disowned(tinfo->get_memory_guarded_delete);
0579 (void) src.release();
0580
0581 return existing_inst;
0582 }
0583 }
0584 throw cast_error("Invalid unique_ptr: another instance owns this pointer already.");
0585 }
0586
0587 auto inst = reinterpret_steal<object>(make_new_instance(tinfo->type));
0588 auto *inst_raw_ptr = reinterpret_cast<instance *>(inst.ptr());
0589 inst_raw_ptr->owned = true;
0590 void *&valueptr = values_and_holders(inst_raw_ptr).begin()->value_ptr();
0591 valueptr = src_raw_void_ptr;
0592
0593 if (static_cast<void *>(src.get()) == src_raw_void_ptr) {
0594
0595
0596 src_raw_void_ptr = nullptr;
0597 }
0598 auto smhldr = smart_holder::from_unique_ptr(std::move(src), src_raw_void_ptr);
0599 tinfo->init_instance(inst_raw_ptr, static_cast<const void *>(&smhldr));
0600
0601 if (policy == return_value_policy::reference_internal) {
0602 keep_alive_impl(inst, parent);
0603 }
0604
0605 return inst.release();
0606 }
0607
0608 template <typename T, typename D>
0609 handle smart_holder_from_unique_ptr(std::unique_ptr<T const, D> &&src,
0610 return_value_policy policy,
0611 handle parent,
0612 const std::pair<const void *, const type_info *> &st) {
0613 return smart_holder_from_unique_ptr(
0614 std::unique_ptr<T, D>(const_cast<T *>(src.release()),
0615 std::move(src.get_deleter())),
0616 policy,
0617 parent,
0618 st);
0619 }
0620
0621 template <typename T>
0622 handle smart_holder_from_shared_ptr(const std::shared_ptr<T> &src,
0623 return_value_policy policy,
0624 handle parent,
0625 const std::pair<const void *, const type_info *> &st) {
0626 switch (policy) {
0627 case return_value_policy::automatic:
0628 case return_value_policy::automatic_reference:
0629 break;
0630 case return_value_policy::take_ownership:
0631 throw cast_error("Invalid return_value_policy for shared_ptr (take_ownership).");
0632 case return_value_policy::copy:
0633 case return_value_policy::move:
0634 break;
0635 case return_value_policy::reference:
0636 throw cast_error("Invalid return_value_policy for shared_ptr (reference).");
0637 case return_value_policy::reference_internal:
0638 break;
0639 }
0640 if (!src) {
0641 return none().release();
0642 }
0643
0644 auto src_raw_ptr = src.get();
0645 assert(st.second != nullptr);
0646 void *src_raw_void_ptr = static_cast<void *>(src_raw_ptr);
0647 const detail::type_info *tinfo = st.second;
0648 if (handle existing_inst = find_registered_python_instance(src_raw_void_ptr, tinfo)) {
0649
0650
0651 return existing_inst;
0652 }
0653
0654 auto inst = reinterpret_steal<object>(make_new_instance(tinfo->type));
0655 auto *inst_raw_ptr = reinterpret_cast<instance *>(inst.ptr());
0656 inst_raw_ptr->owned = true;
0657 void *&valueptr = values_and_holders(inst_raw_ptr).begin()->value_ptr();
0658 valueptr = src_raw_void_ptr;
0659
0660 auto smhldr
0661 = smart_holder::from_shared_ptr(std::shared_ptr<void>(src, const_cast<void *>(st.first)));
0662 tinfo->init_instance(inst_raw_ptr, static_cast<const void *>(&smhldr));
0663
0664 if (policy == return_value_policy::reference_internal) {
0665 keep_alive_impl(inst, parent);
0666 }
0667
0668 return inst.release();
0669 }
0670
0671 template <typename T>
0672 handle smart_holder_from_shared_ptr(const std::shared_ptr<T const> &src,
0673 return_value_policy policy,
0674 handle parent,
0675 const std::pair<const void *, const type_info *> &st) {
0676 return smart_holder_from_shared_ptr(std::const_pointer_cast<T>(src),
0677 policy,
0678 parent,
0679 st);
0680 }
0681
0682 struct shared_ptr_parent_life_support {
0683 PyObject *parent;
0684 explicit shared_ptr_parent_life_support(PyObject *parent) : parent{parent} {
0685 Py_INCREF(parent);
0686 }
0687
0688 void operator()(void *) {
0689 gil_scoped_acquire gil;
0690 Py_DECREF(parent);
0691 }
0692 };
0693
0694 struct shared_ptr_trampoline_self_life_support {
0695 PyObject *self;
0696 explicit shared_ptr_trampoline_self_life_support(instance *inst)
0697 : self{reinterpret_cast<PyObject *>(inst)} {
0698 gil_scoped_acquire gil;
0699 Py_INCREF(self);
0700 }
0701
0702 void operator()(void *) {
0703 gil_scoped_acquire gil;
0704 Py_DECREF(self);
0705 }
0706 };
0707
0708 template <typename T,
0709 typename D,
0710 typename std::enable_if<std::is_default_constructible<D>::value, int>::type = 0>
0711 inline std::unique_ptr<T, D> unique_with_deleter(T *raw_ptr, std::unique_ptr<D> &&deleter) {
0712 if (deleter == nullptr) {
0713 return std::unique_ptr<T, D>(raw_ptr);
0714 }
0715 return std::unique_ptr<T, D>(raw_ptr, std::move(*deleter));
0716 }
0717
0718 template <typename T,
0719 typename D,
0720 typename std::enable_if<!std::is_default_constructible<D>::value, int>::type = 0>
0721 inline std::unique_ptr<T, D> unique_with_deleter(T *raw_ptr, std::unique_ptr<D> &&deleter) {
0722 if (deleter == nullptr) {
0723 pybind11_fail("smart_holder_type_casters: deleter is not default constructible and no"
0724 " instance available to return.");
0725 }
0726 return std::unique_ptr<T, D>(raw_ptr, std::move(*deleter));
0727 }
0728
0729 template <typename T>
0730 struct load_helper : value_and_holder_helper {
0731 bool was_populated = false;
0732 bool python_instance_is_alias = false;
0733
0734 void maybe_set_python_instance_is_alias(handle src) {
0735 if (was_populated) {
0736 python_instance_is_alias = reinterpret_cast<instance *>(src.ptr())->is_alias;
0737 }
0738 }
0739
0740 static std::shared_ptr<T> make_shared_ptr_with_responsible_parent(T *raw_ptr, handle parent) {
0741 return std::shared_ptr<T>(raw_ptr, shared_ptr_parent_life_support(parent.ptr()));
0742 }
0743
0744 std::shared_ptr<T> load_as_shared_ptr(const type_info *tinfo,
0745 void *void_raw_ptr,
0746 handle responsible_parent = nullptr,
0747
0748
0749 bool force_potentially_slicing_shared_ptr
0750 = false) const {
0751 if (!have_holder()) {
0752 return nullptr;
0753 }
0754 throw_if_uninitialized_or_disowned_holder(typeid(T));
0755 smart_holder &hld = holder();
0756 hld.ensure_is_not_disowned("load_as_shared_ptr");
0757 if (hld.vptr_is_using_noop_deleter) {
0758 if (responsible_parent) {
0759 return make_shared_ptr_with_responsible_parent(static_cast<T *>(void_raw_ptr),
0760 responsible_parent);
0761 }
0762 throw std::runtime_error("Non-owning holder (load_as_shared_ptr).");
0763 }
0764 auto *type_raw_ptr = static_cast<T *>(void_raw_ptr);
0765 if (python_instance_is_alias && !force_potentially_slicing_shared_ptr) {
0766 auto *vptr_gd_ptr = tinfo->get_memory_guarded_delete(holder().vptr);
0767 if (vptr_gd_ptr != nullptr) {
0768 std::shared_ptr<void> released_ptr = vptr_gd_ptr->released_ptr.lock();
0769 if (released_ptr) {
0770 return std::shared_ptr<T>(released_ptr, type_raw_ptr);
0771 }
0772 std::shared_ptr<T> to_be_released(
0773 type_raw_ptr, shared_ptr_trampoline_self_life_support(loaded_v_h.inst));
0774 vptr_gd_ptr->released_ptr = to_be_released;
0775 return to_be_released;
0776 }
0777 auto *sptsls_ptr = std::get_deleter<shared_ptr_trampoline_self_life_support>(hld.vptr);
0778 if (sptsls_ptr != nullptr) {
0779
0780
0781 if (reinterpret_cast<PyObject *>(loaded_v_h.inst) == sptsls_ptr->self) {
0782 pybind11_fail("smart_holder_type_caster_support load_as_shared_ptr failure: "
0783 "loaded_v_h.inst == sptsls_ptr->self");
0784 }
0785 }
0786 if (sptsls_ptr != nullptr || !memory::type_has_shared_from_this(type_raw_ptr)) {
0787 return std::shared_ptr<T>(
0788 type_raw_ptr, shared_ptr_trampoline_self_life_support(loaded_v_h.inst));
0789 }
0790 if (hld.vptr_is_external_shared_ptr) {
0791 pybind11_fail("smart_holder_type_casters load_as_shared_ptr failure: not "
0792 "implemented: trampoline-self-life-support for external shared_ptr "
0793 "to type inheriting from std::enable_shared_from_this.");
0794 }
0795 pybind11_fail(
0796 "smart_holder_type_casters: load_as_shared_ptr failure: internal inconsistency.");
0797 }
0798 std::shared_ptr<void> void_shd_ptr = hld.template as_shared_ptr<void>();
0799 return std::shared_ptr<T>(void_shd_ptr, type_raw_ptr);
0800 }
0801
0802 template <typename D>
0803 std::unique_ptr<T, D> load_as_unique_ptr(const type_info *tinfo,
0804 void *raw_void_ptr,
0805 const char *context = "load_as_unique_ptr") {
0806 if (!have_holder()) {
0807 return unique_with_deleter<T, D>(nullptr, std::unique_ptr<D>());
0808 }
0809 throw_if_uninitialized_or_disowned_holder(typeid(T));
0810 throw_if_instance_is_currently_owned_by_shared_ptr(tinfo);
0811 holder().ensure_is_not_disowned(context);
0812 holder().template ensure_compatible_uqp_del<T, D>(context);
0813 holder().ensure_use_count_1(context);
0814
0815 T *raw_type_ptr = static_cast<T *>(raw_void_ptr);
0816
0817 auto *self_life_support = tinfo->get_trampoline_self_life_support(raw_type_ptr);
0818
0819 assert(!python_instance_is_alias || self_life_support);
0820
0821 std::unique_ptr<D> extracted_deleter
0822 = holder().template extract_deleter<T, D>(context, tinfo->get_memory_guarded_delete);
0823
0824
0825 if (self_life_support != nullptr) {
0826 holder().disown(tinfo->get_memory_guarded_delete);
0827 } else {
0828 holder().release_ownership(tinfo->get_memory_guarded_delete);
0829 }
0830 auto result = unique_with_deleter<T, D>(raw_type_ptr, std::move(extracted_deleter));
0831 if (self_life_support != nullptr) {
0832 self_life_support->activate_life_support(loaded_v_h);
0833 } else {
0834 void *value_void_ptr = loaded_v_h.value_ptr();
0835 loaded_v_h.value_ptr() = nullptr;
0836 deregister_instance(loaded_v_h.inst, value_void_ptr, loaded_v_h.type);
0837 }
0838
0839
0840 return result;
0841 }
0842
0843
0844
0845 template <typename D>
0846 std::unique_ptr<T, D> load_as_const_unique_ptr(const type_info *tinfo,
0847 T *raw_type_ptr,
0848 const char *context
0849 = "load_as_const_unique_ptr") {
0850 if (!have_holder()) {
0851 return unique_with_deleter<T, D>(nullptr, std::unique_ptr<D>());
0852 }
0853 holder().template ensure_compatible_uqp_del<T, D>(context);
0854 return unique_with_deleter<T, D>(raw_type_ptr,
0855 std::move(holder().template extract_deleter<T, D>(
0856 context, tinfo->get_memory_guarded_delete)));
0857 }
0858 };
0859
0860 PYBIND11_NAMESPACE_END(smart_holder_type_caster_support)
0861
0862 class type_caster_generic {
0863 public:
0864 PYBIND11_NOINLINE explicit type_caster_generic(const std::type_info &type_info)
0865 : typeinfo(get_type_info(type_info)), cpptype(&type_info) {}
0866
0867 explicit type_caster_generic(const type_info *typeinfo)
0868 : typeinfo(typeinfo), cpptype(typeinfo ? typeinfo->cpptype : nullptr) {}
0869
0870 bool load(handle src, bool convert) { return load_impl<type_caster_generic>(src, convert); }
0871
0872 PYBIND11_NOINLINE static handle cast(const void *_src,
0873 return_value_policy policy,
0874 handle parent,
0875 const detail::type_info *tinfo,
0876 void *(*copy_constructor)(const void *),
0877 void *(*move_constructor)(const void *),
0878 const void *existing_holder = nullptr) {
0879 if (!tinfo) {
0880 return handle();
0881 }
0882
0883 void *src = const_cast<void *>(_src);
0884 if (src == nullptr) {
0885 return none().release();
0886 }
0887
0888 if (handle registered_inst = find_registered_python_instance(src, tinfo)) {
0889 return registered_inst;
0890 }
0891
0892 auto inst = reinterpret_steal<object>(make_new_instance(tinfo->type));
0893 auto *wrapper = reinterpret_cast<instance *>(inst.ptr());
0894 wrapper->owned = false;
0895 void *&valueptr = values_and_holders(wrapper).begin()->value_ptr();
0896
0897 switch (policy) {
0898 case return_value_policy::automatic:
0899 case return_value_policy::take_ownership:
0900 valueptr = src;
0901 wrapper->owned = true;
0902 break;
0903
0904 case return_value_policy::automatic_reference:
0905 case return_value_policy::reference:
0906 valueptr = src;
0907 wrapper->owned = false;
0908 break;
0909
0910 case return_value_policy::copy:
0911 if (copy_constructor) {
0912 valueptr = copy_constructor(src);
0913 } else {
0914 #if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
0915 std::string type_name(tinfo->cpptype->name());
0916 detail::clean_type_id(type_name);
0917 throw cast_error("return_value_policy = copy, but type " + type_name
0918 + " is non-copyable!");
0919 #else
0920 throw cast_error("return_value_policy = copy, but type is "
0921 "non-copyable! (#define PYBIND11_DETAILED_ERROR_MESSAGES or "
0922 "compile in debug mode for details)");
0923 #endif
0924 }
0925 wrapper->owned = true;
0926 break;
0927
0928 case return_value_policy::move:
0929 if (move_constructor) {
0930 valueptr = move_constructor(src);
0931 } else if (copy_constructor) {
0932 valueptr = copy_constructor(src);
0933 } else {
0934 #if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
0935 std::string type_name(tinfo->cpptype->name());
0936 detail::clean_type_id(type_name);
0937 throw cast_error("return_value_policy = move, but type " + type_name
0938 + " is neither movable nor copyable!");
0939 #else
0940 throw cast_error("return_value_policy = move, but type is neither "
0941 "movable nor copyable! "
0942 "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in "
0943 "debug mode for details)");
0944 #endif
0945 }
0946 wrapper->owned = true;
0947 break;
0948
0949 case return_value_policy::reference_internal:
0950 valueptr = src;
0951 wrapper->owned = false;
0952 keep_alive_impl(inst, parent);
0953 break;
0954
0955 default:
0956 throw cast_error("unhandled return_value_policy: should not happen!");
0957 }
0958
0959 tinfo->init_instance(wrapper, existing_holder);
0960
0961 return inst.release();
0962 }
0963
0964
0965 void load_value(value_and_holder &&v_h) {
0966 if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
0967 smart_holder_type_caster_support::value_and_holder_helper v_h_helper;
0968 v_h_helper.loaded_v_h = v_h;
0969 if (v_h_helper.have_holder()) {
0970 v_h_helper.throw_if_uninitialized_or_disowned_holder(cpptype->name());
0971 value = v_h_helper.holder().template as_raw_ptr_unowned<void>();
0972 return;
0973 }
0974 }
0975 auto *&vptr = v_h.value_ptr();
0976
0977 if (vptr == nullptr) {
0978 const auto *type = v_h.type ? v_h.type : typeinfo;
0979 if (type->operator_new) {
0980 vptr = type->operator_new(type->type_size);
0981 } else {
0982 #if defined(__cpp_aligned_new) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
0983 if (type->type_align > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
0984 vptr = ::operator new(type->type_size, std::align_val_t(type->type_align));
0985 } else {
0986 vptr = ::operator new(type->type_size);
0987 }
0988 #else
0989 vptr = ::operator new(type->type_size);
0990 #endif
0991 }
0992 }
0993 value = vptr;
0994 }
0995 bool try_implicit_casts(handle src, bool convert) {
0996 for (const auto &cast : typeinfo->implicit_casts) {
0997 type_caster_generic sub_caster(*cast.first);
0998 if (sub_caster.load(src, convert)) {
0999 value = cast.second(sub_caster.value);
1000 return true;
1001 }
1002 }
1003 return false;
1004 }
1005 bool try_direct_conversions(handle src) {
1006 for (auto &converter : *typeinfo->direct_conversions) {
1007 if (converter(src.ptr(), value)) {
1008 return true;
1009 }
1010 }
1011 return false;
1012 }
1013 bool try_cpp_conduit(handle src) {
1014 value = try_raw_pointer_ephemeral_from_cpp_conduit(src, cpptype);
1015 if (value != nullptr) {
1016 return true;
1017 }
1018 return false;
1019 }
1020 void check_holder_compat() {}
1021
1022 PYBIND11_NOINLINE static void *local_load(PyObject *src, const type_info *ti) {
1023 auto caster = type_caster_generic(ti);
1024 if (caster.load(src, false)) {
1025 return caster.value;
1026 }
1027 return nullptr;
1028 }
1029
1030
1031
1032 PYBIND11_NOINLINE bool try_load_foreign_module_local(handle src) {
1033 constexpr auto *local_key = PYBIND11_MODULE_LOCAL_ID;
1034 const auto pytype = type::handle_of(src);
1035 if (!hasattr(pytype, local_key)) {
1036 return false;
1037 }
1038
1039 type_info *foreign_typeinfo = reinterpret_borrow<capsule>(getattr(pytype, local_key));
1040
1041
1042 if (foreign_typeinfo->module_local_load == &local_load
1043 || (cpptype && !same_type(*cpptype, *foreign_typeinfo->cpptype))) {
1044 return false;
1045 }
1046
1047 if (auto *result = foreign_typeinfo->module_local_load(src.ptr(), foreign_typeinfo)) {
1048 value = result;
1049 return true;
1050 }
1051 return false;
1052 }
1053
1054
1055
1056
1057 template <typename ThisT>
1058 PYBIND11_NOINLINE bool load_impl(handle src, bool convert) {
1059 if (!src) {
1060 return false;
1061 }
1062 if (!typeinfo) {
1063 return try_load_foreign_module_local(src);
1064 }
1065
1066 auto &this_ = static_cast<ThisT &>(*this);
1067 this_.check_holder_compat();
1068
1069 PyTypeObject *srctype = Py_TYPE(src.ptr());
1070
1071
1072
1073 if (srctype == typeinfo->type) {
1074 this_.load_value(reinterpret_cast<instance *>(src.ptr())->get_value_and_holder());
1075 return true;
1076 }
1077
1078 if (PyType_IsSubtype(srctype, typeinfo->type)) {
1079 const auto &bases = all_type_info(srctype);
1080 bool no_cpp_mi = typeinfo->simple_type;
1081
1082
1083
1084
1085
1086
1087
1088 if (bases.size() == 1 && (no_cpp_mi || bases.front()->type == typeinfo->type)) {
1089 this_.load_value(reinterpret_cast<instance *>(src.ptr())->get_value_and_holder());
1090 return true;
1091 }
1092
1093
1094
1095 if (bases.size() > 1) {
1096 for (auto *base : bases) {
1097 if (no_cpp_mi ? PyType_IsSubtype(base->type, typeinfo->type)
1098 : base->type == typeinfo->type) {
1099 this_.load_value(
1100 reinterpret_cast<instance *>(src.ptr())->get_value_and_holder(base));
1101 return true;
1102 }
1103 }
1104 }
1105
1106
1107
1108
1109 if (this_.try_implicit_casts(src, convert)) {
1110 return true;
1111 }
1112 }
1113
1114
1115 if (convert) {
1116 for (const auto &converter : typeinfo->implicit_conversions) {
1117 auto temp = reinterpret_steal<object>(converter(src.ptr(), typeinfo->type));
1118 if (load_impl<ThisT>(temp, false)) {
1119 loader_life_support::add_patient(temp);
1120 return true;
1121 }
1122 }
1123 if (this_.try_direct_conversions(src)) {
1124 return true;
1125 }
1126 }
1127
1128
1129 if (typeinfo->module_local) {
1130 if (auto *gtype = get_global_type_info(*typeinfo->cpptype)) {
1131 typeinfo = gtype;
1132 return load(src, false);
1133 }
1134 }
1135
1136
1137 if (try_load_foreign_module_local(src)) {
1138 return true;
1139 }
1140
1141
1142 if (src.is_none()) {
1143
1144 if (!convert) {
1145 return false;
1146 }
1147 value = nullptr;
1148 return true;
1149 }
1150
1151 if (convert && cpptype && this_.try_cpp_conduit(src)) {
1152 return true;
1153 }
1154
1155 return false;
1156 }
1157
1158
1159
1160
1161 PYBIND11_NOINLINE static std::pair<const void *, const type_info *>
1162 src_and_type(const void *src,
1163 const std::type_info &cast_type,
1164 const std::type_info *rtti_type = nullptr) {
1165 if (auto *tpi = get_type_info(cast_type)) {
1166 return {src, const_cast<const type_info *>(tpi)};
1167 }
1168
1169
1170 std::string tname = rtti_type ? rtti_type->name() : cast_type.name();
1171 detail::clean_type_id(tname);
1172 std::string msg = "Unregistered type : " + tname;
1173 set_error(PyExc_TypeError, msg.c_str());
1174 return {nullptr, nullptr};
1175 }
1176
1177 const type_info *typeinfo = nullptr;
1178 const std::type_info *cpptype = nullptr;
1179 void *value = nullptr;
1180 };
1181
1182 inline object cpp_conduit_method(handle self,
1183 const bytes &pybind11_platform_abi_id,
1184 const capsule &cpp_type_info_capsule,
1185 const bytes &pointer_kind) {
1186 #ifdef PYBIND11_HAS_STRING_VIEW
1187 using cpp_str = std::string_view;
1188 #else
1189 using cpp_str = std::string;
1190 #endif
1191 if (cpp_str(pybind11_platform_abi_id) != PYBIND11_PLATFORM_ABI_ID) {
1192 return none();
1193 }
1194 if (std::strcmp(cpp_type_info_capsule.name(), typeid(std::type_info).name()) != 0) {
1195 return none();
1196 }
1197 if (cpp_str(pointer_kind) != "raw_pointer_ephemeral") {
1198 throw std::runtime_error("Invalid pointer_kind: \"" + std::string(pointer_kind) + "\"");
1199 }
1200 const auto *cpp_type_info = cpp_type_info_capsule.get_pointer<const std::type_info>();
1201 type_caster_generic caster(*cpp_type_info);
1202 if (!caster.load(self, false)) {
1203 return none();
1204 }
1205 return capsule(caster.value, cpp_type_info->name());
1206 }
1207
1208
1209
1210
1211
1212
1213
1214
1215 template <typename T>
1216 using cast_op_type = conditional_t<std::is_pointer<remove_reference_t<T>>::value,
1217 typename std::add_pointer<intrinsic_t<T>>::type,
1218 typename std::add_lvalue_reference<intrinsic_t<T>>::type>;
1219
1220
1221
1222
1223
1224
1225
1226
1227 template <typename T>
1228 using movable_cast_op_type
1229 = conditional_t<std::is_pointer<typename std::remove_reference<T>::type>::value,
1230 typename std::add_pointer<intrinsic_t<T>>::type,
1231 conditional_t<std::is_rvalue_reference<T>::value,
1232 typename std::add_rvalue_reference<intrinsic_t<T>>::type,
1233 typename std::add_lvalue_reference<intrinsic_t<T>>::type>>;
1234
1235
1236
1237 template <typename Container, typename SFINAE = void>
1238 struct container_mapped_type_traits {
1239 static constexpr bool has_mapped_type = false;
1240 static constexpr bool has_recursive_mapped_type = false;
1241 };
1242
1243 template <typename Container>
1244 struct container_mapped_type_traits<
1245 Container,
1246 typename std::enable_if<
1247 std::is_same<typename Container::mapped_type, Container>::value>::type> {
1248 static constexpr bool has_mapped_type = true;
1249 static constexpr bool has_recursive_mapped_type = true;
1250 };
1251
1252 template <typename Container>
1253 struct container_mapped_type_traits<
1254 Container,
1255 typename std::enable_if<
1256 negation<std::is_same<typename Container::mapped_type, Container>>::value>::type> {
1257 static constexpr bool has_mapped_type = true;
1258 static constexpr bool has_recursive_mapped_type = false;
1259 };
1260
1261
1262
1263 template <typename Container, typename SFINAE = void>
1264 struct container_value_type_traits : std::false_type {
1265 static constexpr bool has_value_type = false;
1266 static constexpr bool has_recursive_value_type = false;
1267 };
1268
1269 template <typename Container>
1270 struct container_value_type_traits<
1271 Container,
1272 typename std::enable_if<
1273 std::is_same<typename Container::value_type, Container>::value>::type> {
1274 static constexpr bool has_value_type = true;
1275 static constexpr bool has_recursive_value_type = true;
1276 };
1277
1278 template <typename Container>
1279 struct container_value_type_traits<
1280 Container,
1281 typename std::enable_if<
1282 negation<std::is_same<typename Container::value_type, Container>>::value>::type> {
1283 static constexpr bool has_value_type = true;
1284 static constexpr bool has_recursive_value_type = false;
1285 };
1286
1287
1288
1289
1290
1291 struct recursive_bottom {};
1292
1293
1294
1295
1296
1297
1298 template <typename T, bool is_this_a_map>
1299 struct impl_type_to_check_recursively {
1300
1301
1302
1303 using if_recursive = recursive_bottom;
1304
1305
1306
1307 using if_not_recursive = T;
1308 };
1309
1310
1311
1312
1313
1314
1315 template <typename A, typename B>
1316 struct impl_type_to_check_recursively<std::pair<A, B>, true> {
1317 using if_recursive = typename std::remove_const<A>::type;
1318 using if_not_recursive = std::pair<typename std::remove_const<A>::type, B>;
1319 };
1320
1321
1322
1323
1324 template <typename Container, typename SFINAE = void>
1325 struct impl_recursive_container_traits {
1326 using type_to_check_recursively = recursive_bottom;
1327 };
1328
1329 template <typename Container>
1330 struct impl_recursive_container_traits<
1331 Container,
1332 typename std::enable_if<container_value_type_traits<Container>::has_value_type>::type> {
1333 static constexpr bool is_recursive
1334 = container_mapped_type_traits<Container>::has_recursive_mapped_type
1335 || container_value_type_traits<Container>::has_recursive_value_type;
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345 using type_to_check_recursively = typename std::conditional<
1346 is_recursive,
1347 typename impl_type_to_check_recursively<
1348 typename Container::value_type,
1349 container_mapped_type_traits<Container>::has_mapped_type>::if_recursive,
1350 typename impl_type_to_check_recursively<
1351 typename Container::value_type,
1352 container_mapped_type_traits<Container>::has_mapped_type>::if_not_recursive>::type;
1353 };
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378 template <typename Container, typename SFINAE = void>
1379 struct recursive_container_traits : impl_recursive_container_traits<Container> {};
1380
1381 template <typename T>
1382 struct is_move_constructible
1383 : all_of<std::is_move_constructible<T>,
1384 is_move_constructible<
1385 typename recursive_container_traits<T>::type_to_check_recursively>> {};
1386
1387 template <>
1388 struct is_move_constructible<recursive_bottom> : std::true_type {};
1389
1390
1391
1392
1393
1394 template <typename T1, typename T2>
1395 struct is_move_constructible<std::pair<T1, T2>>
1396 : all_of<is_move_constructible<T1>, is_move_constructible<T2>> {};
1397
1398
1399
1400 template <typename T>
1401 struct is_copy_constructible
1402 : all_of<std::is_copy_constructible<T>,
1403 is_copy_constructible<
1404 typename recursive_container_traits<T>::type_to_check_recursively>> {};
1405
1406 template <>
1407 struct is_copy_constructible<recursive_bottom> : std::true_type {};
1408
1409
1410
1411
1412
1413 template <typename T1, typename T2>
1414 struct is_copy_constructible<std::pair<T1, T2>>
1415 : all_of<is_copy_constructible<T1>, is_copy_constructible<T2>> {};
1416
1417
1418 template <typename T>
1419 struct is_copy_assignable
1420 : all_of<
1421 std::is_copy_assignable<T>,
1422 is_copy_assignable<typename recursive_container_traits<T>::type_to_check_recursively>> {
1423 };
1424
1425 template <>
1426 struct is_copy_assignable<recursive_bottom> : std::true_type {};
1427
1428 template <typename T1, typename T2>
1429 struct is_copy_assignable<std::pair<T1, T2>>
1430 : all_of<is_copy_assignable<T1>, is_copy_assignable<T2>> {};
1431
1432 PYBIND11_NAMESPACE_END(detail)
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455 template <typename itype, typename SFINAE = void>
1456 struct polymorphic_type_hook_base {
1457 static const void *get(const itype *src, const std::type_info *&) { return src; }
1458 };
1459 template <typename itype>
1460 struct polymorphic_type_hook_base<itype, detail::enable_if_t<std::is_polymorphic<itype>::value>> {
1461 static const void *get(const itype *src, const std::type_info *&type) {
1462 type = src ? &typeid(*src) : nullptr;
1463 return dynamic_cast<const void *>(src);
1464 }
1465 };
1466 template <typename itype, typename SFINAE = void>
1467 struct polymorphic_type_hook : public polymorphic_type_hook_base<itype> {};
1468
1469 PYBIND11_NAMESPACE_BEGIN(detail)
1470
1471
1472 template <typename type>
1473 class type_caster_base : public type_caster_generic {
1474 using itype = intrinsic_t<type>;
1475
1476 public:
1477 static constexpr auto name = const_name<type>();
1478
1479 type_caster_base() : type_caster_base(typeid(type)) {}
1480 explicit type_caster_base(const std::type_info &info) : type_caster_generic(info) {}
1481
1482 static handle cast(const itype &src, return_value_policy policy, handle parent) {
1483 if (policy == return_value_policy::automatic
1484 || policy == return_value_policy::automatic_reference) {
1485 policy = return_value_policy::copy;
1486 }
1487 return cast(std::addressof(src), policy, parent);
1488 }
1489
1490 static handle cast(itype &&src, return_value_policy, handle parent) {
1491 return cast(std::addressof(src), return_value_policy::move, parent);
1492 }
1493
1494
1495
1496
1497 static std::pair<const void *, const type_info *> src_and_type(const itype *src) {
1498 const auto &cast_type = typeid(itype);
1499 const std::type_info *instance_type = nullptr;
1500 const void *vsrc = polymorphic_type_hook<itype>::get(src, instance_type);
1501 if (instance_type && !same_type(cast_type, *instance_type)) {
1502
1503
1504
1505
1506
1507
1508
1509
1510 if (const auto *tpi = get_type_info(*instance_type)) {
1511 return {vsrc, tpi};
1512 }
1513 }
1514
1515
1516 return type_caster_generic::src_and_type(src, cast_type, instance_type);
1517 }
1518
1519 static handle cast(const itype *src, return_value_policy policy, handle parent) {
1520 auto st = src_and_type(src);
1521 return type_caster_generic::cast(st.first,
1522 policy,
1523 parent,
1524 st.second,
1525 make_copy_constructor(src),
1526 make_move_constructor(src));
1527 }
1528
1529 static handle cast_holder(const itype *src, const void *holder) {
1530 auto st = src_and_type(src);
1531 return type_caster_generic::cast(st.first,
1532 return_value_policy::take_ownership,
1533 {},
1534 st.second,
1535 nullptr,
1536 nullptr,
1537 holder);
1538 }
1539
1540 template <typename T>
1541 using cast_op_type = detail::cast_op_type<T>;
1542
1543
1544 operator itype *() { return (type *) value; }
1545
1546 operator itype &() {
1547 if (!value) {
1548 throw reference_cast_error();
1549 }
1550 return *((itype *) value);
1551 }
1552
1553 protected:
1554 using Constructor = void *(*) (const void *);
1555
1556
1557
1558
1559 template <typename T, typename = enable_if_t<is_copy_constructible<T>::value>>
1560 static auto make_copy_constructor(const T *)
1561 -> decltype(new T(std::declval<const T>()), Constructor{}) {
1562 return [](const void *arg) -> void * { return new T(*reinterpret_cast<const T *>(arg)); };
1563 }
1564
1565 template <typename T, typename = enable_if_t<is_move_constructible<T>::value>>
1566 static auto make_move_constructor(const T *)
1567 -> decltype(new T(std::declval<T &&>()), Constructor{}) {
1568 return [](const void *arg) -> void * {
1569 return new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(arg))));
1570 };
1571 }
1572
1573 static Constructor make_copy_constructor(...) { return nullptr; }
1574 static Constructor make_move_constructor(...) { return nullptr; }
1575 };
1576
1577 inline std::string quote_cpp_type_name(const std::string &cpp_type_name) {
1578 return cpp_type_name;
1579 }
1580
1581 PYBIND11_NOINLINE std::string type_info_description(const std::type_info &ti) {
1582 if (auto *type_data = get_type_info(ti)) {
1583 handle th((PyObject *) type_data->type);
1584 return th.attr("__module__").cast<std::string>() + '.'
1585 + th.attr("__qualname__").cast<std::string>();
1586 }
1587 return quote_cpp_type_name(clean_type_id(ti.name()));
1588 }
1589
1590 PYBIND11_NAMESPACE_END(detail)
1591 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)