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