File indexing completed on 2026-11-02 10:28:14
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 static handle cast_non_owning(const cast_sources &srcs,
1008 return_value_policy policy,
1009 handle parent,
1010 const void *existing_holder = nullptr) {
1011
1012
1013 assert(policy == return_value_policy::reference
1014 || policy == return_value_policy::reference_internal
1015 || policy == return_value_policy::automatic_reference);
1016 return cast(srcs, policy, parent, nullptr, nullptr, existing_holder);
1017 }
1018
1019 PYBIND11_NOINLINE static handle cast(const cast_sources &srcs,
1020 return_value_policy policy,
1021 handle parent,
1022 void *(*copy_constructor)(const void *),
1023 void *(*move_constructor)(const void *),
1024 const void *existing_holder = nullptr) {
1025 if (!srcs.result.tinfo) {
1026
1027 std::string tname = srcs.downcast.cpptype ? srcs.downcast.cpptype->name()
1028 : srcs.original.cpptype ? srcs.original.cpptype->name()
1029 : "<unspecified>";
1030 detail::clean_type_id(tname);
1031 std::string msg = "Unregistered type : " + tname;
1032 set_error(PyExc_TypeError, msg.c_str());
1033 return handle();
1034 }
1035
1036 void *src = const_cast<void *>(srcs.result.cppobj);
1037 if (src == nullptr) {
1038 return none().release();
1039 }
1040 const type_info *tinfo = srcs.result.tinfo;
1041
1042 if (handle registered_inst = find_registered_python_instance(src, tinfo)) {
1043 return registered_inst;
1044 }
1045
1046 auto inst = reinterpret_steal<object>(make_new_instance(tinfo->type));
1047 auto *wrapper = reinterpret_cast<instance *>(inst.ptr());
1048 wrapper->owned = false;
1049 void *&valueptr = values_and_holders(wrapper).begin()->value_ptr();
1050
1051 switch (policy) {
1052 case return_value_policy::automatic:
1053 case return_value_policy::take_ownership:
1054 valueptr = src;
1055 wrapper->owned = true;
1056 break;
1057
1058 case return_value_policy::automatic_reference:
1059 case return_value_policy::reference:
1060 valueptr = src;
1061 wrapper->owned = false;
1062 break;
1063
1064 case return_value_policy::copy:
1065 if (copy_constructor) {
1066 valueptr = copy_constructor(src);
1067 } else {
1068 #if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
1069 std::string type_name(tinfo->cpptype->name());
1070 detail::clean_type_id(type_name);
1071 throw cast_error("return_value_policy = copy, but type " + type_name
1072 + " is non-copyable!");
1073 #else
1074 throw cast_error("return_value_policy = copy, but type is "
1075 "non-copyable! (#define PYBIND11_DETAILED_ERROR_MESSAGES or "
1076 "compile in debug mode for details)");
1077 #endif
1078 }
1079 wrapper->owned = true;
1080 break;
1081
1082 case return_value_policy::move:
1083 if (move_constructor) {
1084 valueptr = move_constructor(src);
1085 } else if (copy_constructor) {
1086 valueptr = copy_constructor(src);
1087 } else {
1088 #if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
1089 std::string type_name(tinfo->cpptype->name());
1090 detail::clean_type_id(type_name);
1091 throw cast_error("return_value_policy = move, but type " + type_name
1092 + " is neither movable nor copyable!");
1093 #else
1094 throw cast_error("return_value_policy = move, but type is neither "
1095 "movable nor copyable! "
1096 "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in "
1097 "debug mode for details)");
1098 #endif
1099 }
1100 wrapper->owned = true;
1101 break;
1102
1103 case return_value_policy::reference_internal:
1104 valueptr = src;
1105 wrapper->owned = false;
1106 keep_alive_impl(inst, parent);
1107 break;
1108
1109 default:
1110 throw cast_error("unhandled return_value_policy: should not happen!");
1111 }
1112
1113 tinfo->init_instance(wrapper, existing_holder);
1114
1115 return inst.release();
1116 }
1117
1118
1119 void load_value(value_and_holder &&v_h) {
1120 if (typeinfo->holder_enum_v == detail::holder_enum_t::smart_holder) {
1121 smart_holder_type_caster_support::value_and_holder_helper v_h_helper;
1122 v_h_helper.loaded_v_h = v_h;
1123 if (v_h_helper.have_holder()) {
1124 v_h_helper.throw_if_uninitialized_or_disowned_holder(cpptype->name());
1125 value = v_h_helper.holder().template as_raw_ptr_unowned<void>();
1126 return;
1127 }
1128 }
1129 auto *&vptr = v_h.value_ptr();
1130
1131 if (vptr == nullptr) {
1132 const auto *type = v_h.type ? v_h.type : typeinfo;
1133 if (type->operator_new) {
1134 vptr = type->operator_new(type->type_size);
1135 } else {
1136 #if defined(__cpp_aligned_new) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
1137 if (type->type_align > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
1138 vptr = ::operator new(type->type_size, std::align_val_t(type->type_align));
1139 } else {
1140 vptr = ::operator new(type->type_size);
1141 }
1142 #else
1143 vptr = ::operator new(type->type_size);
1144 #endif
1145 }
1146 }
1147 value = vptr;
1148 }
1149 bool try_implicit_casts(handle src, bool convert) {
1150 for (const auto &cast : typeinfo->implicit_casts) {
1151 type_caster_generic sub_caster(*cast.first);
1152 if (sub_caster.load(src, convert)) {
1153 value = cast.second(sub_caster.value);
1154 return true;
1155 }
1156 }
1157 return false;
1158 }
1159 bool try_direct_conversions(handle src) {
1160 for (auto &converter : *typeinfo->direct_conversions) {
1161 if (converter(src.ptr(), value)) {
1162 return true;
1163 }
1164 }
1165 return false;
1166 }
1167 bool try_cpp_conduit(handle src) {
1168 value = try_raw_pointer_ephemeral_from_cpp_conduit(src, cpptype);
1169 if (value != nullptr) {
1170 return true;
1171 }
1172 return false;
1173 }
1174 void check_holder_compat() {}
1175 bool set_foreign_holder(handle) { return true; }
1176
1177 PYBIND11_NOINLINE static void *local_load(PyObject *src, const type_info *ti) {
1178 auto caster = type_caster_generic(ti);
1179 if (caster.load(src, false)) {
1180 return caster.value;
1181 }
1182 return nullptr;
1183 }
1184
1185
1186
1187 PYBIND11_NOINLINE bool try_load_foreign_module_local(handle src) {
1188 constexpr auto *local_key = PYBIND11_MODULE_LOCAL_ID;
1189 const auto pytype = type::handle_of(src);
1190 if (!hasattr(pytype, local_key)) {
1191 return false;
1192 }
1193
1194 type_info *foreign_typeinfo = reinterpret_borrow<capsule>(getattr(pytype, local_key));
1195
1196
1197 if (foreign_typeinfo->module_local_load == &local_load
1198 || (cpptype && !same_type(*cpptype, *foreign_typeinfo->cpptype))) {
1199 return false;
1200 }
1201
1202 if (auto *result = foreign_typeinfo->module_local_load(src.ptr(), foreign_typeinfo)) {
1203 value = result;
1204 return true;
1205 }
1206 return false;
1207 }
1208
1209
1210
1211
1212 template <typename ThisT>
1213 PYBIND11_NOINLINE bool load_impl(handle src, bool convert) {
1214 auto &this_ = static_cast<ThisT &>(*this);
1215 if (!src) {
1216 return false;
1217 }
1218 if (!typeinfo) {
1219 return try_load_foreign_module_local(src) && this_.set_foreign_holder(src);
1220 }
1221
1222 this_.check_holder_compat();
1223
1224 PyTypeObject *srctype = Py_TYPE(src.ptr());
1225
1226
1227
1228 if (srctype == typeinfo->type) {
1229 this_.load_value(reinterpret_cast<instance *>(src.ptr())->get_value_and_holder());
1230 return true;
1231 }
1232
1233 if (PyType_IsSubtype(srctype, typeinfo->type)) {
1234 const auto &bases = all_type_info(srctype);
1235 bool no_cpp_mi = typeinfo->simple_type;
1236
1237
1238
1239
1240
1241
1242
1243 if (bases.size() == 1 && (no_cpp_mi || bases.front()->type == typeinfo->type)) {
1244 this_.load_value(reinterpret_cast<instance *>(src.ptr())->get_value_and_holder());
1245 return true;
1246 }
1247
1248
1249
1250 if (bases.size() > 1) {
1251 for (auto *base : bases) {
1252 if (no_cpp_mi ? PyType_IsSubtype(base->type, typeinfo->type)
1253 : base->type == typeinfo->type) {
1254 this_.load_value(
1255 reinterpret_cast<instance *>(src.ptr())->get_value_and_holder(base));
1256 return true;
1257 }
1258 }
1259 }
1260
1261
1262
1263
1264 if (this_.try_implicit_casts(src, convert)) {
1265 return true;
1266 }
1267 }
1268
1269
1270 if (convert) {
1271 for (const auto &converter : typeinfo->implicit_conversions) {
1272 auto temp = reinterpret_steal<object>(converter(src.ptr(), typeinfo->type));
1273 if (load_impl<ThisT>(temp, false)) {
1274 loader_life_support::add_patient(temp);
1275 return true;
1276 }
1277 }
1278 if (this_.try_direct_conversions(src)) {
1279 return true;
1280 }
1281 }
1282
1283
1284 if (typeinfo->module_local) {
1285 if (auto *gtype = get_global_type_info(*typeinfo->cpptype)) {
1286 typeinfo = gtype;
1287 return load_impl<ThisT>(src, false);
1288 }
1289 }
1290
1291
1292 if (try_load_foreign_module_local(src)) {
1293 return this_.set_foreign_holder(src);
1294 }
1295
1296
1297 if (src.is_none()) {
1298
1299 if (!convert) {
1300 return false;
1301 }
1302 value = nullptr;
1303 return true;
1304 }
1305
1306 if (convert && cpptype && this_.try_cpp_conduit(src)) {
1307 return this_.set_foreign_holder(src);
1308 }
1309
1310 return false;
1311 }
1312
1313 const type_info *typeinfo = nullptr;
1314 const std::type_info *cpptype = nullptr;
1315 void *value = nullptr;
1316 };
1317
1318 inline object cpp_conduit_method(handle self,
1319 const bytes &pybind11_platform_abi_id,
1320 const capsule &cpp_type_info_capsule,
1321 const bytes &pointer_kind) {
1322 #ifdef PYBIND11_HAS_STRING_VIEW
1323 using cpp_str = std::string_view;
1324 #else
1325 using cpp_str = std::string;
1326 #endif
1327 if (cpp_str(pybind11_platform_abi_id) != PYBIND11_PLATFORM_ABI_ID) {
1328 return none();
1329 }
1330 if (std::strcmp(cpp_type_info_capsule.name(), typeid(std::type_info).name()) != 0) {
1331 return none();
1332 }
1333 if (cpp_str(pointer_kind) != "raw_pointer_ephemeral") {
1334 throw std::runtime_error("Invalid pointer_kind: \"" + std::string(pointer_kind) + "\"");
1335 }
1336 const auto *cpp_type_info = cpp_type_info_capsule.get_pointer<const std::type_info>();
1337 type_caster_generic caster(*cpp_type_info);
1338 if (!caster.load(self, false)) {
1339 return none();
1340 }
1341 return capsule(caster.value, cpp_type_info->name());
1342 }
1343
1344
1345
1346
1347
1348
1349
1350
1351 template <typename T>
1352 using cast_op_type = conditional_t<std::is_pointer<remove_reference_t<T>>::value,
1353 typename std::add_pointer<intrinsic_t<T>>::type,
1354 typename std::add_lvalue_reference<intrinsic_t<T>>::type>;
1355
1356
1357
1358
1359
1360
1361
1362
1363 template <typename T>
1364 using movable_cast_op_type
1365 = conditional_t<std::is_pointer<typename std::remove_reference<T>::type>::value,
1366 typename std::add_pointer<intrinsic_t<T>>::type,
1367 conditional_t<std::is_rvalue_reference<T>::value,
1368 typename std::add_rvalue_reference<intrinsic_t<T>>::type,
1369 typename std::add_lvalue_reference<intrinsic_t<T>>::type>>;
1370
1371
1372
1373 template <typename Container, typename SFINAE = void>
1374 struct container_mapped_type_traits {
1375 static constexpr bool has_mapped_type = false;
1376 static constexpr bool has_recursive_mapped_type = false;
1377 };
1378
1379 template <typename Container>
1380 struct container_mapped_type_traits<
1381 Container,
1382 typename std::enable_if<
1383 std::is_same<typename Container::mapped_type, Container>::value>::type> {
1384 static constexpr bool has_mapped_type = true;
1385 static constexpr bool has_recursive_mapped_type = true;
1386 };
1387
1388 template <typename Container>
1389 struct container_mapped_type_traits<
1390 Container,
1391 typename std::enable_if<
1392 negation<std::is_same<typename Container::mapped_type, Container>>::value>::type> {
1393 static constexpr bool has_mapped_type = true;
1394 static constexpr bool has_recursive_mapped_type = false;
1395 };
1396
1397
1398
1399 template <typename Container, typename SFINAE = void>
1400 struct container_value_type_traits : std::false_type {
1401 static constexpr bool has_value_type = false;
1402 static constexpr bool has_recursive_value_type = false;
1403 };
1404
1405 template <typename Container>
1406 struct container_value_type_traits<
1407 Container,
1408 typename std::enable_if<
1409 std::is_same<typename Container::value_type, Container>::value>::type> {
1410 static constexpr bool has_value_type = true;
1411 static constexpr bool has_recursive_value_type = true;
1412 };
1413
1414 template <typename Container>
1415 struct container_value_type_traits<
1416 Container,
1417 typename std::enable_if<
1418 negation<std::is_same<typename Container::value_type, Container>>::value>::type> {
1419 static constexpr bool has_value_type = true;
1420 static constexpr bool has_recursive_value_type = false;
1421 };
1422
1423
1424
1425
1426
1427 struct recursive_bottom {};
1428
1429
1430
1431
1432
1433
1434 template <typename T, bool is_this_a_map>
1435 struct impl_type_to_check_recursively {
1436
1437
1438
1439 using if_recursive = recursive_bottom;
1440
1441
1442
1443 using if_not_recursive = T;
1444 };
1445
1446
1447
1448
1449
1450
1451 template <typename A, typename B>
1452 struct impl_type_to_check_recursively<std::pair<A, B>, true> {
1453 using if_recursive = typename std::remove_const<A>::type;
1454 using if_not_recursive = std::pair<typename std::remove_const<A>::type, B>;
1455 };
1456
1457
1458
1459
1460 template <typename Container, typename SFINAE = void>
1461 struct impl_recursive_container_traits {
1462 using type_to_check_recursively = recursive_bottom;
1463 };
1464
1465 template <typename Container>
1466 struct impl_recursive_container_traits<
1467 Container,
1468 typename std::enable_if<container_value_type_traits<Container>::has_value_type>::type> {
1469 static constexpr bool is_recursive
1470 = container_mapped_type_traits<Container>::has_recursive_mapped_type
1471 || container_value_type_traits<Container>::has_recursive_value_type;
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481 using type_to_check_recursively = typename std::conditional<
1482 is_recursive,
1483 typename impl_type_to_check_recursively<
1484 typename Container::value_type,
1485 container_mapped_type_traits<Container>::has_mapped_type>::if_recursive,
1486 typename impl_type_to_check_recursively<
1487 typename Container::value_type,
1488 container_mapped_type_traits<Container>::has_mapped_type>::if_not_recursive>::type;
1489 };
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514 template <typename Container, typename SFINAE = void>
1515 struct recursive_container_traits : impl_recursive_container_traits<Container> {};
1516
1517 template <typename T>
1518 struct is_move_constructible
1519 : all_of<std::is_move_constructible<T>,
1520 is_move_constructible<
1521 typename recursive_container_traits<T>::type_to_check_recursively>> {};
1522
1523 template <>
1524 struct is_move_constructible<recursive_bottom> : std::true_type {};
1525
1526
1527
1528
1529
1530 template <typename T1, typename T2>
1531 struct is_move_constructible<std::pair<T1, T2>>
1532 : all_of<is_move_constructible<T1>, is_move_constructible<T2>> {};
1533
1534
1535
1536 template <typename T>
1537 struct is_copy_constructible
1538 : all_of<std::is_copy_constructible<T>,
1539 is_copy_constructible<
1540 typename recursive_container_traits<T>::type_to_check_recursively>> {};
1541
1542 template <>
1543 struct is_copy_constructible<recursive_bottom> : std::true_type {};
1544
1545
1546
1547
1548
1549 template <typename T1, typename T2>
1550 struct is_copy_constructible<std::pair<T1, T2>>
1551 : all_of<is_copy_constructible<T1>, is_copy_constructible<T2>> {};
1552
1553
1554 template <typename T>
1555 struct is_copy_assignable
1556 : all_of<
1557 std::is_copy_assignable<T>,
1558 is_copy_assignable<typename recursive_container_traits<T>::type_to_check_recursively>> {
1559 };
1560
1561 template <>
1562 struct is_copy_assignable<recursive_bottom> : std::true_type {};
1563
1564 template <typename T1, typename T2>
1565 struct is_copy_assignable<std::pair<T1, T2>>
1566 : all_of<is_copy_assignable<T1>, is_copy_assignable<T2>> {};
1567
1568 PYBIND11_NAMESPACE_END(detail)
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591 template <typename itype, typename SFINAE = void>
1592 struct polymorphic_type_hook_base {
1593 static const void *get(const itype *src, const std::type_info *&) { return src; }
1594 };
1595 template <typename itype>
1596 struct polymorphic_type_hook_base<itype, detail::enable_if_t<std::is_polymorphic<itype>::value>> {
1597 static const void *get(const itype *src, const std::type_info *&type) {
1598 type = src ? &typeid(*src) : nullptr;
1599 return dynamic_cast<const void *>(src);
1600 }
1601 };
1602 template <typename itype, typename SFINAE = void>
1603 struct polymorphic_type_hook : public polymorphic_type_hook_base<itype> {};
1604
1605 PYBIND11_NAMESPACE_BEGIN(detail)
1606
1607 template <typename itype>
1608 cast_sources::cast_sources(const itype *ptr) : original{ptr, &typeid(itype)} {
1609
1610
1611
1612
1613
1614
1615
1616
1617 downcast.cppobj = polymorphic_type_hook<itype>::get(ptr, downcast.cpptype);
1618 result = resolve();
1619 }
1620
1621
1622 template <typename type>
1623 class type_caster_base : public type_caster_generic {
1624 using itype = intrinsic_t<type>;
1625
1626 public:
1627 static constexpr auto name = const_name<type>();
1628
1629 type_caster_base() : type_caster_base(typeid(type)) {}
1630 explicit type_caster_base(const std::type_info &info) : type_caster_generic(info) {}
1631
1632
1633
1634
1635 struct cast_sources : detail::cast_sources {
1636 explicit cast_sources(const itype *ptr) : detail::cast_sources(ptr) {}
1637 };
1638
1639 static handle cast(const itype &src, return_value_policy policy, handle parent) {
1640 if (policy == return_value_policy::automatic
1641 || policy == return_value_policy::automatic_reference) {
1642 policy = return_value_policy::copy;
1643 }
1644 return cast(std::addressof(src), policy, parent);
1645 }
1646
1647 static handle cast(itype &&src, return_value_policy, handle parent) {
1648 return cast(std::addressof(src), return_value_policy::move, parent);
1649 }
1650
1651 static handle cast(const itype *src, return_value_policy policy, handle parent) {
1652 return cast(cast_sources{src}, policy, parent);
1653 }
1654
1655 static handle cast(const cast_sources &srcs, return_value_policy policy, handle parent) {
1656 return type_caster_generic::cast(srcs,
1657 policy,
1658 parent,
1659 make_copy_constructor((const itype *) nullptr),
1660 make_move_constructor((const itype *) nullptr));
1661 }
1662
1663 static handle cast_holder(const itype *src, const void *holder) {
1664 return cast_holder(cast_sources{src}, holder);
1665 }
1666
1667 static handle cast_holder(const cast_sources &srcs, const void *holder) {
1668 auto policy = return_value_policy::take_ownership;
1669 return type_caster_generic::cast(srcs, policy, {}, nullptr, nullptr, holder);
1670 }
1671
1672 template <typename T>
1673 using cast_op_type = detail::cast_op_type<T>;
1674
1675
1676 operator itype *() { return (type *) value; }
1677
1678 operator itype &() {
1679 if (!value) {
1680 throw reference_cast_error();
1681 }
1682 return *((itype *) value);
1683 }
1684
1685 protected:
1686 using Constructor = void *(*) (const void *);
1687
1688
1689
1690
1691 template <typename T, typename = enable_if_t<is_copy_constructible<T>::value>>
1692 static auto make_copy_constructor(const T *)
1693 -> decltype(new T(std::declval<const T>()), Constructor{}) {
1694 return [](const void *arg) -> void * { return new T(*reinterpret_cast<const T *>(arg)); };
1695 }
1696
1697 template <typename T, typename = enable_if_t<is_move_constructible<T>::value>>
1698 static auto make_move_constructor(const T *)
1699 -> decltype(new T(std::declval<T &&>()), Constructor{}) {
1700 return [](const void *arg) -> void * {
1701 return new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(arg))));
1702 };
1703 }
1704
1705 static Constructor make_copy_constructor(...) { return nullptr; }
1706 static Constructor make_move_constructor(...) { return nullptr; }
1707 };
1708
1709 inline std::string quote_cpp_type_name(const std::string &cpp_type_name) {
1710 return cpp_type_name;
1711 }
1712
1713 PYBIND11_NOINLINE std::string type_info_description(const std::type_info &ti) {
1714 if (auto *type_data = get_type_info(ti)) {
1715 handle th(reinterpret_cast<PyObject *>(type_data->type));
1716 return th.attr("__module__").cast<std::string>() + '.'
1717 + th.attr("__qualname__").cast<std::string>();
1718 }
1719 return quote_cpp_type_name(clean_type_id(ti.name()));
1720 }
1721
1722 PYBIND11_NAMESPACE_END(detail)
1723 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)