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