File indexing completed on 2025-01-18 10:06:12
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #pragma once
0011
0012 #include <pybind11/pytypes.h>
0013
0014 #include "common.h"
0015 #include "descr.h"
0016 #include "internals.h"
0017 #include "typeid.h"
0018 #include "value_and_holder.h"
0019
0020 #include <cstdint>
0021 #include <iterator>
0022 #include <new>
0023 #include <string>
0024 #include <type_traits>
0025 #include <typeindex>
0026 #include <typeinfo>
0027 #include <unordered_map>
0028 #include <utility>
0029 #include <vector>
0030
0031 PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
0032 PYBIND11_NAMESPACE_BEGIN(detail)
0033
0034
0035
0036 class loader_life_support {
0037 private:
0038 loader_life_support *parent = nullptr;
0039 std::unordered_set<PyObject *> keep_alive;
0040
0041
0042 static PYBIND11_TLS_KEY_REF get_stack_tls_key() {
0043 #if PYBIND11_INTERNALS_VERSION == 4
0044 return get_local_internals().loader_life_support_tls_key;
0045 #else
0046 return get_internals().loader_life_support_tls_key;
0047 #endif
0048 }
0049 static loader_life_support *get_stack_top() {
0050 return static_cast<loader_life_support *>(PYBIND11_TLS_GET_VALUE(get_stack_tls_key()));
0051 }
0052 static void set_stack_top(loader_life_support *value) {
0053 PYBIND11_TLS_REPLACE_VALUE(get_stack_tls_key(), value);
0054 }
0055
0056 public:
0057
0058 loader_life_support() : parent{get_stack_top()} { set_stack_top(this); }
0059
0060
0061 ~loader_life_support() {
0062 if (get_stack_top() != this) {
0063 pybind11_fail("loader_life_support: internal error");
0064 }
0065 set_stack_top(parent);
0066 for (auto *item : keep_alive) {
0067 Py_DECREF(item);
0068 }
0069 }
0070
0071
0072
0073 PYBIND11_NOINLINE static void add_patient(handle h) {
0074 loader_life_support *frame = get_stack_top();
0075 if (!frame) {
0076
0077
0078
0079
0080 throw cast_error("When called outside a bound function, py::cast() cannot "
0081 "do Python -> C++ conversions which require the creation "
0082 "of temporary values");
0083 }
0084
0085 if (frame->keep_alive.insert(h.ptr()).second) {
0086 Py_INCREF(h.ptr());
0087 }
0088 }
0089 };
0090
0091
0092
0093
0094 inline std::pair<decltype(internals::registered_types_py)::iterator, bool>
0095 all_type_info_get_cache(PyTypeObject *type);
0096
0097
0098 inline void all_type_info_add_base_most_derived_first(std::vector<type_info *> &bases,
0099 type_info *addl_base) {
0100 for (auto it = bases.begin(); it != bases.end(); it++) {
0101 type_info *existing_base = *it;
0102 if (PyType_IsSubtype(addl_base->type, existing_base->type) != 0) {
0103 bases.insert(it, addl_base);
0104 return;
0105 }
0106 }
0107 bases.push_back(addl_base);
0108 }
0109
0110
0111 PYBIND11_NOINLINE void all_type_info_populate(PyTypeObject *t, std::vector<type_info *> &bases) {
0112 assert(bases.empty());
0113 std::vector<PyTypeObject *> check;
0114 for (handle parent : reinterpret_borrow<tuple>(t->tp_bases)) {
0115 check.push_back((PyTypeObject *) parent.ptr());
0116 }
0117
0118 auto const &type_dict = get_internals().registered_types_py;
0119 for (size_t i = 0; i < check.size(); i++) {
0120 auto *type = check[i];
0121
0122 if (!PyType_Check((PyObject *) type)) {
0123 continue;
0124 }
0125
0126
0127 auto it = type_dict.find(type);
0128 if (it != type_dict.end()) {
0129
0130
0131
0132
0133 for (auto *tinfo : it->second) {
0134
0135
0136
0137 bool found = false;
0138 for (auto *known : bases) {
0139 if (known == tinfo) {
0140 found = true;
0141 break;
0142 }
0143 }
0144 if (!found) {
0145 all_type_info_add_base_most_derived_first(bases, tinfo);
0146 }
0147 }
0148 } else if (type->tp_bases) {
0149
0150
0151 if (i + 1 == check.size()) {
0152
0153
0154
0155 check.pop_back();
0156 i--;
0157 }
0158 for (handle parent : reinterpret_borrow<tuple>(type->tp_bases)) {
0159 check.push_back((PyTypeObject *) parent.ptr());
0160 }
0161 }
0162 }
0163 }
0164
0165
0166
0167
0168
0169
0170
0171
0172
0173
0174
0175 inline const std::vector<detail::type_info *> &all_type_info(PyTypeObject *type) {
0176 auto ins = all_type_info_get_cache(type);
0177 if (ins.second) {
0178
0179 all_type_info_populate(type, ins.first->second);
0180 }
0181
0182 return ins.first->second;
0183 }
0184
0185
0186
0187
0188
0189
0190 PYBIND11_NOINLINE detail::type_info *get_type_info(PyTypeObject *type) {
0191 const auto &bases = all_type_info(type);
0192 if (bases.empty()) {
0193 return nullptr;
0194 }
0195 if (bases.size() > 1) {
0196 pybind11_fail(
0197 "pybind11::detail::get_type_info: type has multiple pybind11-registered bases");
0198 }
0199 return bases.front();
0200 }
0201
0202 inline detail::type_info *get_local_type_info(const std::type_index &tp) {
0203 auto &locals = get_local_internals().registered_types_cpp;
0204 auto it = locals.find(tp);
0205 if (it != locals.end()) {
0206 return it->second;
0207 }
0208 return nullptr;
0209 }
0210
0211 inline detail::type_info *get_global_type_info(const std::type_index &tp) {
0212 return with_internals([&](internals &internals) {
0213 detail::type_info *type_info = nullptr;
0214 auto &types = internals.registered_types_cpp;
0215 auto it = types.find(tp);
0216 if (it != types.end()) {
0217 type_info = it->second;
0218 }
0219 return type_info;
0220 });
0221 }
0222
0223
0224
0225 PYBIND11_NOINLINE detail::type_info *get_type_info(const std::type_index &tp,
0226 bool throw_if_missing = false) {
0227 if (auto *ltype = get_local_type_info(tp)) {
0228 return ltype;
0229 }
0230 if (auto *gtype = get_global_type_info(tp)) {
0231 return gtype;
0232 }
0233
0234 if (throw_if_missing) {
0235 std::string tname = tp.name();
0236 detail::clean_type_id(tname);
0237 pybind11_fail("pybind11::detail::get_type_info: unable to find type info for \""
0238 + std::move(tname) + '"');
0239 }
0240 return nullptr;
0241 }
0242
0243 PYBIND11_NOINLINE handle get_type_handle(const std::type_info &tp, bool throw_if_missing) {
0244 detail::type_info *type_info = get_type_info(tp, throw_if_missing);
0245 return handle(type_info ? ((PyObject *) type_info->type) : nullptr);
0246 }
0247
0248
0249 PYBIND11_NOINLINE handle find_registered_python_instance(void *src,
0250 const detail::type_info *tinfo) {
0251 return with_instance_map(src, [&](instance_map &instances) {
0252 auto it_instances = instances.equal_range(src);
0253 for (auto it_i = it_instances.first; it_i != it_instances.second; ++it_i) {
0254 for (auto *instance_type : detail::all_type_info(Py_TYPE(it_i->second))) {
0255 if (instance_type && same_type(*instance_type->cpptype, *tinfo->cpptype)) {
0256 return handle((PyObject *) it_i->second).inc_ref();
0257 }
0258 }
0259 }
0260 return handle();
0261 });
0262 }
0263
0264
0265 struct values_and_holders {
0266 private:
0267 instance *inst;
0268 using type_vec = std::vector<detail::type_info *>;
0269 const type_vec &tinfo;
0270
0271 public:
0272 explicit values_and_holders(instance *inst)
0273 : inst{inst}, tinfo(all_type_info(Py_TYPE(inst))) {}
0274
0275 explicit values_and_holders(PyObject *obj)
0276 : inst{nullptr}, tinfo(all_type_info(Py_TYPE(obj))) {
0277 if (!tinfo.empty()) {
0278 inst = reinterpret_cast<instance *>(obj);
0279 }
0280 }
0281
0282 struct iterator {
0283 private:
0284 instance *inst = nullptr;
0285 const type_vec *types = nullptr;
0286 value_and_holder curr;
0287 friend struct values_and_holders;
0288 iterator(instance *inst, const type_vec *tinfo) : inst{inst}, types{tinfo} {
0289 if (inst != nullptr) {
0290 assert(!types->empty());
0291 curr = value_and_holder(
0292 inst ,
0293 (*types)[0] ,
0294 0,
0295 0 );
0296 }
0297 }
0298
0299 explicit iterator(size_t end) : curr(end) {}
0300
0301 public:
0302 bool operator==(const iterator &other) const { return curr.index == other.curr.index; }
0303 bool operator!=(const iterator &other) const { return curr.index != other.curr.index; }
0304 iterator &operator++() {
0305 if (!inst->simple_layout) {
0306 curr.vh += 1 + (*types)[curr.index]->holder_size_in_ptrs;
0307 }
0308 ++curr.index;
0309 curr.type = curr.index < types->size() ? (*types)[curr.index] : nullptr;
0310 return *this;
0311 }
0312 value_and_holder &operator*() { return curr; }
0313 value_and_holder *operator->() { return &curr; }
0314 };
0315
0316 iterator begin() { return iterator(inst, &tinfo); }
0317 iterator end() { return iterator(tinfo.size()); }
0318
0319 iterator find(const type_info *find_type) {
0320 auto it = begin(), endit = end();
0321 while (it != endit && it->type != find_type) {
0322 ++it;
0323 }
0324 return it;
0325 }
0326
0327 size_t size() { return tinfo.size(); }
0328
0329
0330 bool is_redundant_value_and_holder(const value_and_holder &vh) {
0331 for (size_t i = 0; i < vh.index; i++) {
0332 if (PyType_IsSubtype(tinfo[i]->type, tinfo[vh.index]->type) != 0) {
0333 return true;
0334 }
0335 }
0336 return false;
0337 }
0338 };
0339
0340
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350 PYBIND11_NOINLINE value_and_holder
0351 instance::get_value_and_holder(const type_info *find_type ,
0352 bool throw_if_missing ) {
0353
0354 if (!find_type || Py_TYPE(this) == find_type->type) {
0355 return value_and_holder(this, find_type, 0, 0);
0356 }
0357
0358 detail::values_and_holders vhs(this);
0359 auto it = vhs.find(find_type);
0360 if (it != vhs.end()) {
0361 return *it;
0362 }
0363
0364 if (!throw_if_missing) {
0365 return value_and_holder();
0366 }
0367
0368 #if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
0369 pybind11_fail("pybind11::detail::instance::get_value_and_holder: `"
0370 + get_fully_qualified_tp_name(find_type->type)
0371 + "' is not a pybind11 base of the given `"
0372 + get_fully_qualified_tp_name(Py_TYPE(this)) + "' instance");
0373 #else
0374 pybind11_fail(
0375 "pybind11::detail::instance::get_value_and_holder: "
0376 "type is not a pybind11 base of the given instance "
0377 "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for type details)");
0378 #endif
0379 }
0380
0381 PYBIND11_NOINLINE void instance::allocate_layout() {
0382 const auto &tinfo = all_type_info(Py_TYPE(this));
0383
0384 const size_t n_types = tinfo.size();
0385
0386 if (n_types == 0) {
0387 pybind11_fail(
0388 "instance allocation failed: new instance has no pybind11-registered base types");
0389 }
0390
0391 simple_layout
0392 = n_types == 1 && tinfo.front()->holder_size_in_ptrs <= instance_simple_holder_in_ptrs();
0393
0394
0395 if (simple_layout) {
0396 simple_value_holder[0] = nullptr;
0397 simple_holder_constructed = false;
0398 simple_instance_registered = false;
0399 } else {
0400
0401
0402
0403
0404 size_t space = 0;
0405 for (auto *t : tinfo) {
0406 space += 1;
0407 space += t->holder_size_in_ptrs;
0408 }
0409 size_t flags_at = space;
0410 space += size_in_ptrs(n_types);
0411
0412
0413
0414
0415
0416
0417
0418
0419 nonsimple.values_and_holders = (void **) PyMem_Calloc(space, sizeof(void *));
0420 if (!nonsimple.values_and_holders) {
0421 throw std::bad_alloc();
0422 }
0423 nonsimple.status
0424 = reinterpret_cast<std::uint8_t *>(&nonsimple.values_and_holders[flags_at]);
0425 }
0426 owned = true;
0427 }
0428
0429
0430 PYBIND11_NOINLINE void instance::deallocate_layout() {
0431 if (!simple_layout) {
0432 PyMem_Free(reinterpret_cast<void *>(nonsimple.values_and_holders));
0433 }
0434 }
0435
0436 PYBIND11_NOINLINE bool isinstance_generic(handle obj, const std::type_info &tp) {
0437 handle type = detail::get_type_handle(tp, false);
0438 if (!type) {
0439 return false;
0440 }
0441 return isinstance(obj, type);
0442 }
0443
0444 PYBIND11_NOINLINE handle get_object_handle(const void *ptr, const detail::type_info *type) {
0445 return with_instance_map(ptr, [&](instance_map &instances) {
0446 auto range = instances.equal_range(ptr);
0447 for (auto it = range.first; it != range.second; ++it) {
0448 for (const auto &vh : values_and_holders(it->second)) {
0449 if (vh.type == type) {
0450 return handle((PyObject *) it->second);
0451 }
0452 }
0453 }
0454 return handle();
0455 });
0456 }
0457
0458 inline PyThreadState *get_thread_state_unchecked() {
0459 #if defined(PYPY_VERSION)
0460 return PyThreadState_GET();
0461 #elif PY_VERSION_HEX < 0x030D0000
0462 return _PyThreadState_UncheckedGet();
0463 #else
0464 return PyThreadState_GetUnchecked();
0465 #endif
0466 }
0467
0468
0469 void keep_alive_impl(handle nurse, handle patient);
0470 inline PyObject *make_new_instance(PyTypeObject *type);
0471
0472 class type_caster_generic {
0473 public:
0474 PYBIND11_NOINLINE explicit type_caster_generic(const std::type_info &type_info)
0475 : typeinfo(get_type_info(type_info)), cpptype(&type_info) {}
0476
0477 explicit type_caster_generic(const type_info *typeinfo)
0478 : typeinfo(typeinfo), cpptype(typeinfo ? typeinfo->cpptype : nullptr) {}
0479
0480 bool load(handle src, bool convert) { return load_impl<type_caster_generic>(src, convert); }
0481
0482 PYBIND11_NOINLINE static handle cast(const void *_src,
0483 return_value_policy policy,
0484 handle parent,
0485 const detail::type_info *tinfo,
0486 void *(*copy_constructor)(const void *),
0487 void *(*move_constructor)(const void *),
0488 const void *existing_holder = nullptr) {
0489 if (!tinfo) {
0490 return handle();
0491 }
0492
0493 void *src = const_cast<void *>(_src);
0494 if (src == nullptr) {
0495 return none().release();
0496 }
0497
0498 if (handle registered_inst = find_registered_python_instance(src, tinfo)) {
0499 return registered_inst;
0500 }
0501
0502 auto inst = reinterpret_steal<object>(make_new_instance(tinfo->type));
0503 auto *wrapper = reinterpret_cast<instance *>(inst.ptr());
0504 wrapper->owned = false;
0505 void *&valueptr = values_and_holders(wrapper).begin()->value_ptr();
0506
0507 switch (policy) {
0508 case return_value_policy::automatic:
0509 case return_value_policy::take_ownership:
0510 valueptr = src;
0511 wrapper->owned = true;
0512 break;
0513
0514 case return_value_policy::automatic_reference:
0515 case return_value_policy::reference:
0516 valueptr = src;
0517 wrapper->owned = false;
0518 break;
0519
0520 case return_value_policy::copy:
0521 if (copy_constructor) {
0522 valueptr = copy_constructor(src);
0523 } else {
0524 #if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
0525 std::string type_name(tinfo->cpptype->name());
0526 detail::clean_type_id(type_name);
0527 throw cast_error("return_value_policy = copy, but type " + type_name
0528 + " is non-copyable!");
0529 #else
0530 throw cast_error("return_value_policy = copy, but type is "
0531 "non-copyable! (#define PYBIND11_DETAILED_ERROR_MESSAGES or "
0532 "compile in debug mode for details)");
0533 #endif
0534 }
0535 wrapper->owned = true;
0536 break;
0537
0538 case return_value_policy::move:
0539 if (move_constructor) {
0540 valueptr = move_constructor(src);
0541 } else if (copy_constructor) {
0542 valueptr = copy_constructor(src);
0543 } else {
0544 #if defined(PYBIND11_DETAILED_ERROR_MESSAGES)
0545 std::string type_name(tinfo->cpptype->name());
0546 detail::clean_type_id(type_name);
0547 throw cast_error("return_value_policy = move, but type " + type_name
0548 + " is neither movable nor copyable!");
0549 #else
0550 throw cast_error("return_value_policy = move, but type is neither "
0551 "movable nor copyable! "
0552 "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in "
0553 "debug mode for details)");
0554 #endif
0555 }
0556 wrapper->owned = true;
0557 break;
0558
0559 case return_value_policy::reference_internal:
0560 valueptr = src;
0561 wrapper->owned = false;
0562 keep_alive_impl(inst, parent);
0563 break;
0564
0565 default:
0566 throw cast_error("unhandled return_value_policy: should not happen!");
0567 }
0568
0569 tinfo->init_instance(wrapper, existing_holder);
0570
0571 return inst.release();
0572 }
0573
0574
0575 void load_value(value_and_holder &&v_h) {
0576 auto *&vptr = v_h.value_ptr();
0577
0578 if (vptr == nullptr) {
0579 const auto *type = v_h.type ? v_h.type : typeinfo;
0580 if (type->operator_new) {
0581 vptr = type->operator_new(type->type_size);
0582 } else {
0583 #if defined(__cpp_aligned_new) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
0584 if (type->type_align > __STDCPP_DEFAULT_NEW_ALIGNMENT__) {
0585 vptr = ::operator new(type->type_size, std::align_val_t(type->type_align));
0586 } else {
0587 vptr = ::operator new(type->type_size);
0588 }
0589 #else
0590 vptr = ::operator new(type->type_size);
0591 #endif
0592 }
0593 }
0594 value = vptr;
0595 }
0596 bool try_implicit_casts(handle src, bool convert) {
0597 for (const auto &cast : typeinfo->implicit_casts) {
0598 type_caster_generic sub_caster(*cast.first);
0599 if (sub_caster.load(src, convert)) {
0600 value = cast.second(sub_caster.value);
0601 return true;
0602 }
0603 }
0604 return false;
0605 }
0606 bool try_direct_conversions(handle src) {
0607 for (auto &converter : *typeinfo->direct_conversions) {
0608 if (converter(src.ptr(), value)) {
0609 return true;
0610 }
0611 }
0612 return false;
0613 }
0614 void check_holder_compat() {}
0615
0616 PYBIND11_NOINLINE static void *local_load(PyObject *src, const type_info *ti) {
0617 auto caster = type_caster_generic(ti);
0618 if (caster.load(src, false)) {
0619 return caster.value;
0620 }
0621 return nullptr;
0622 }
0623
0624
0625
0626 PYBIND11_NOINLINE bool try_load_foreign_module_local(handle src) {
0627 constexpr auto *local_key = PYBIND11_MODULE_LOCAL_ID;
0628 const auto pytype = type::handle_of(src);
0629 if (!hasattr(pytype, local_key)) {
0630 return false;
0631 }
0632
0633 type_info *foreign_typeinfo = reinterpret_borrow<capsule>(getattr(pytype, local_key));
0634
0635
0636 if (foreign_typeinfo->module_local_load == &local_load
0637 || (cpptype && !same_type(*cpptype, *foreign_typeinfo->cpptype))) {
0638 return false;
0639 }
0640
0641 if (auto *result = foreign_typeinfo->module_local_load(src.ptr(), foreign_typeinfo)) {
0642 value = result;
0643 return true;
0644 }
0645 return false;
0646 }
0647
0648
0649
0650
0651 template <typename ThisT>
0652 PYBIND11_NOINLINE bool load_impl(handle src, bool convert) {
0653 if (!src) {
0654 return false;
0655 }
0656 if (!typeinfo) {
0657 return try_load_foreign_module_local(src);
0658 }
0659
0660 auto &this_ = static_cast<ThisT &>(*this);
0661 this_.check_holder_compat();
0662
0663 PyTypeObject *srctype = Py_TYPE(src.ptr());
0664
0665
0666
0667 if (srctype == typeinfo->type) {
0668 this_.load_value(reinterpret_cast<instance *>(src.ptr())->get_value_and_holder());
0669 return true;
0670 }
0671
0672 if (PyType_IsSubtype(srctype, typeinfo->type)) {
0673 const auto &bases = all_type_info(srctype);
0674 bool no_cpp_mi = typeinfo->simple_type;
0675
0676
0677
0678
0679
0680
0681
0682 if (bases.size() == 1 && (no_cpp_mi || bases.front()->type == typeinfo->type)) {
0683 this_.load_value(reinterpret_cast<instance *>(src.ptr())->get_value_and_holder());
0684 return true;
0685 }
0686
0687
0688
0689 if (bases.size() > 1) {
0690 for (auto *base : bases) {
0691 if (no_cpp_mi ? PyType_IsSubtype(base->type, typeinfo->type)
0692 : base->type == typeinfo->type) {
0693 this_.load_value(
0694 reinterpret_cast<instance *>(src.ptr())->get_value_and_holder(base));
0695 return true;
0696 }
0697 }
0698 }
0699
0700
0701
0702
0703 if (this_.try_implicit_casts(src, convert)) {
0704 return true;
0705 }
0706 }
0707
0708
0709 if (convert) {
0710 for (const auto &converter : typeinfo->implicit_conversions) {
0711 auto temp = reinterpret_steal<object>(converter(src.ptr(), typeinfo->type));
0712 if (load_impl<ThisT>(temp, false)) {
0713 loader_life_support::add_patient(temp);
0714 return true;
0715 }
0716 }
0717 if (this_.try_direct_conversions(src)) {
0718 return true;
0719 }
0720 }
0721
0722
0723 if (typeinfo->module_local) {
0724 if (auto *gtype = get_global_type_info(*typeinfo->cpptype)) {
0725 typeinfo = gtype;
0726 return load(src, false);
0727 }
0728 }
0729
0730
0731 if (try_load_foreign_module_local(src)) {
0732 return true;
0733 }
0734
0735
0736 if (src.is_none()) {
0737
0738 if (!convert) {
0739 return false;
0740 }
0741 value = nullptr;
0742 return true;
0743 }
0744
0745 return false;
0746 }
0747
0748
0749
0750
0751 PYBIND11_NOINLINE static std::pair<const void *, const type_info *>
0752 src_and_type(const void *src,
0753 const std::type_info &cast_type,
0754 const std::type_info *rtti_type = nullptr) {
0755 if (auto *tpi = get_type_info(cast_type)) {
0756 return {src, const_cast<const type_info *>(tpi)};
0757 }
0758
0759
0760 std::string tname = rtti_type ? rtti_type->name() : cast_type.name();
0761 detail::clean_type_id(tname);
0762 std::string msg = "Unregistered type : " + tname;
0763 set_error(PyExc_TypeError, msg.c_str());
0764 return {nullptr, nullptr};
0765 }
0766
0767 const type_info *typeinfo = nullptr;
0768 const std::type_info *cpptype = nullptr;
0769 void *value = nullptr;
0770 };
0771
0772
0773
0774
0775
0776
0777
0778
0779 template <typename T>
0780 using cast_op_type = conditional_t<std::is_pointer<remove_reference_t<T>>::value,
0781 typename std::add_pointer<intrinsic_t<T>>::type,
0782 typename std::add_lvalue_reference<intrinsic_t<T>>::type>;
0783
0784
0785
0786
0787
0788
0789
0790
0791 template <typename T>
0792 using movable_cast_op_type
0793 = conditional_t<std::is_pointer<typename std::remove_reference<T>::type>::value,
0794 typename std::add_pointer<intrinsic_t<T>>::type,
0795 conditional_t<std::is_rvalue_reference<T>::value,
0796 typename std::add_rvalue_reference<intrinsic_t<T>>::type,
0797 typename std::add_lvalue_reference<intrinsic_t<T>>::type>>;
0798
0799
0800
0801 template <typename Container, typename SFINAE = void>
0802 struct container_mapped_type_traits {
0803 static constexpr bool has_mapped_type = false;
0804 static constexpr bool has_recursive_mapped_type = false;
0805 };
0806
0807 template <typename Container>
0808 struct container_mapped_type_traits<
0809 Container,
0810 typename std::enable_if<
0811 std::is_same<typename Container::mapped_type, Container>::value>::type> {
0812 static constexpr bool has_mapped_type = true;
0813 static constexpr bool has_recursive_mapped_type = true;
0814 };
0815
0816 template <typename Container>
0817 struct container_mapped_type_traits<
0818 Container,
0819 typename std::enable_if<
0820 negation<std::is_same<typename Container::mapped_type, Container>>::value>::type> {
0821 static constexpr bool has_mapped_type = true;
0822 static constexpr bool has_recursive_mapped_type = false;
0823 };
0824
0825
0826
0827 template <typename Container, typename SFINAE = void>
0828 struct container_value_type_traits : std::false_type {
0829 static constexpr bool has_value_type = false;
0830 static constexpr bool has_recursive_value_type = false;
0831 };
0832
0833 template <typename Container>
0834 struct container_value_type_traits<
0835 Container,
0836 typename std::enable_if<
0837 std::is_same<typename Container::value_type, Container>::value>::type> {
0838 static constexpr bool has_value_type = true;
0839 static constexpr bool has_recursive_value_type = true;
0840 };
0841
0842 template <typename Container>
0843 struct container_value_type_traits<
0844 Container,
0845 typename std::enable_if<
0846 negation<std::is_same<typename Container::value_type, Container>>::value>::type> {
0847 static constexpr bool has_value_type = true;
0848 static constexpr bool has_recursive_value_type = false;
0849 };
0850
0851
0852
0853
0854
0855 struct recursive_bottom {};
0856
0857
0858
0859
0860
0861
0862 template <typename T, bool is_this_a_map>
0863 struct impl_type_to_check_recursively {
0864
0865
0866
0867 using if_recursive = recursive_bottom;
0868
0869
0870
0871 using if_not_recursive = T;
0872 };
0873
0874
0875
0876
0877
0878
0879 template <typename A, typename B>
0880 struct impl_type_to_check_recursively<std::pair<A, B>, true> {
0881 using if_recursive = typename std::remove_const<A>::type;
0882 using if_not_recursive = std::pair<typename std::remove_const<A>::type, B>;
0883 };
0884
0885
0886
0887
0888 template <typename Container, typename SFINAE = void>
0889 struct impl_recursive_container_traits {
0890 using type_to_check_recursively = recursive_bottom;
0891 };
0892
0893 template <typename Container>
0894 struct impl_recursive_container_traits<
0895 Container,
0896 typename std::enable_if<container_value_type_traits<Container>::has_value_type>::type> {
0897 static constexpr bool is_recursive
0898 = container_mapped_type_traits<Container>::has_recursive_mapped_type
0899 || container_value_type_traits<Container>::has_recursive_value_type;
0900
0901
0902
0903
0904
0905
0906
0907
0908
0909 using type_to_check_recursively = typename std::conditional<
0910 is_recursive,
0911 typename impl_type_to_check_recursively<
0912 typename Container::value_type,
0913 container_mapped_type_traits<Container>::has_mapped_type>::if_recursive,
0914 typename impl_type_to_check_recursively<
0915 typename Container::value_type,
0916 container_mapped_type_traits<Container>::has_mapped_type>::if_not_recursive>::type;
0917 };
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942 template <typename Container, typename SFINAE = void>
0943 struct recursive_container_traits : impl_recursive_container_traits<Container> {};
0944
0945 template <typename T>
0946 struct is_move_constructible
0947 : all_of<std::is_move_constructible<T>,
0948 is_move_constructible<
0949 typename recursive_container_traits<T>::type_to_check_recursively>> {};
0950
0951 template <>
0952 struct is_move_constructible<recursive_bottom> : std::true_type {};
0953
0954
0955
0956
0957
0958 template <typename T1, typename T2>
0959 struct is_move_constructible<std::pair<T1, T2>>
0960 : all_of<is_move_constructible<T1>, is_move_constructible<T2>> {};
0961
0962
0963
0964 template <typename T>
0965 struct is_copy_constructible
0966 : all_of<std::is_copy_constructible<T>,
0967 is_copy_constructible<
0968 typename recursive_container_traits<T>::type_to_check_recursively>> {};
0969
0970 template <>
0971 struct is_copy_constructible<recursive_bottom> : std::true_type {};
0972
0973
0974
0975
0976
0977 template <typename T1, typename T2>
0978 struct is_copy_constructible<std::pair<T1, T2>>
0979 : all_of<is_copy_constructible<T1>, is_copy_constructible<T2>> {};
0980
0981
0982 template <typename T>
0983 struct is_copy_assignable
0984 : all_of<
0985 std::is_copy_assignable<T>,
0986 is_copy_assignable<typename recursive_container_traits<T>::type_to_check_recursively>> {
0987 };
0988
0989 template <>
0990 struct is_copy_assignable<recursive_bottom> : std::true_type {};
0991
0992 template <typename T1, typename T2>
0993 struct is_copy_assignable<std::pair<T1, T2>>
0994 : all_of<is_copy_assignable<T1>, is_copy_assignable<T2>> {};
0995
0996 PYBIND11_NAMESPACE_END(detail)
0997
0998
0999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019 template <typename itype, typename SFINAE = void>
1020 struct polymorphic_type_hook_base {
1021 static const void *get(const itype *src, const std::type_info *&) { return src; }
1022 };
1023 template <typename itype>
1024 struct polymorphic_type_hook_base<itype, detail::enable_if_t<std::is_polymorphic<itype>::value>> {
1025 static const void *get(const itype *src, const std::type_info *&type) {
1026 type = src ? &typeid(*src) : nullptr;
1027 return dynamic_cast<const void *>(src);
1028 }
1029 };
1030 template <typename itype, typename SFINAE = void>
1031 struct polymorphic_type_hook : public polymorphic_type_hook_base<itype> {};
1032
1033 PYBIND11_NAMESPACE_BEGIN(detail)
1034
1035
1036 template <typename type>
1037 class type_caster_base : public type_caster_generic {
1038 using itype = intrinsic_t<type>;
1039
1040 public:
1041 static constexpr auto name = const_name<type>();
1042
1043 type_caster_base() : type_caster_base(typeid(type)) {}
1044 explicit type_caster_base(const std::type_info &info) : type_caster_generic(info) {}
1045
1046 static handle cast(const itype &src, return_value_policy policy, handle parent) {
1047 if (policy == return_value_policy::automatic
1048 || policy == return_value_policy::automatic_reference) {
1049 policy = return_value_policy::copy;
1050 }
1051 return cast(std::addressof(src), policy, parent);
1052 }
1053
1054 static handle cast(itype &&src, return_value_policy, handle parent) {
1055 return cast(std::addressof(src), return_value_policy::move, parent);
1056 }
1057
1058
1059
1060
1061 static std::pair<const void *, const type_info *> src_and_type(const itype *src) {
1062 const auto &cast_type = typeid(itype);
1063 const std::type_info *instance_type = nullptr;
1064 const void *vsrc = polymorphic_type_hook<itype>::get(src, instance_type);
1065 if (instance_type && !same_type(cast_type, *instance_type)) {
1066
1067
1068
1069
1070
1071
1072
1073
1074 if (const auto *tpi = get_type_info(*instance_type)) {
1075 return {vsrc, tpi};
1076 }
1077 }
1078
1079
1080 return type_caster_generic::src_and_type(src, cast_type, instance_type);
1081 }
1082
1083 static handle cast(const itype *src, return_value_policy policy, handle parent) {
1084 auto st = src_and_type(src);
1085 return type_caster_generic::cast(st.first,
1086 policy,
1087 parent,
1088 st.second,
1089 make_copy_constructor(src),
1090 make_move_constructor(src));
1091 }
1092
1093 static handle cast_holder(const itype *src, const void *holder) {
1094 auto st = src_and_type(src);
1095 return type_caster_generic::cast(st.first,
1096 return_value_policy::take_ownership,
1097 {},
1098 st.second,
1099 nullptr,
1100 nullptr,
1101 holder);
1102 }
1103
1104 template <typename T>
1105 using cast_op_type = detail::cast_op_type<T>;
1106
1107
1108 operator itype *() { return (type *) value; }
1109
1110 operator itype &() {
1111 if (!value) {
1112 throw reference_cast_error();
1113 }
1114 return *((itype *) value);
1115 }
1116
1117 protected:
1118 using Constructor = void *(*) (const void *);
1119
1120
1121
1122
1123 template <typename T, typename = enable_if_t<is_copy_constructible<T>::value>>
1124 static auto make_copy_constructor(const T *) -> decltype(new T(std::declval<const T>()),
1125 Constructor{}) {
1126 return [](const void *arg) -> void * { return new T(*reinterpret_cast<const T *>(arg)); };
1127 }
1128
1129 template <typename T, typename = enable_if_t<is_move_constructible<T>::value>>
1130 static auto make_move_constructor(const T *) -> decltype(new T(std::declval<T &&>()),
1131 Constructor{}) {
1132 return [](const void *arg) -> void * {
1133 return new T(std::move(*const_cast<T *>(reinterpret_cast<const T *>(arg))));
1134 };
1135 }
1136
1137 static Constructor make_copy_constructor(...) { return nullptr; }
1138 static Constructor make_move_constructor(...) { return nullptr; }
1139 };
1140
1141 inline std::string quote_cpp_type_name(const std::string &cpp_type_name) {
1142 return cpp_type_name;
1143 }
1144
1145 PYBIND11_NOINLINE std::string type_info_description(const std::type_info &ti) {
1146 if (auto *type_data = get_type_info(ti)) {
1147 handle th((PyObject *) type_data->type);
1148 return th.attr("__module__").cast<std::string>() + '.'
1149 + th.attr("__qualname__").cast<std::string>();
1150 }
1151 return quote_cpp_type_name(clean_type_id(ti.name()));
1152 }
1153
1154 PYBIND11_NAMESPACE_END(detail)
1155 PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)