diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 84cf8dafa..88ad045c7 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -828,6 +828,84 @@ protected: holder_type holder; }; +// BAKEIN_WIP +template +struct copyable_holder_caster> : public type_caster_base { +public: + using base = type_caster_base; + static_assert(std::is_base_of>::value, + "Holder classes are only supported for custom types"); + using base::base; + using base::cast; + using base::typeinfo; + using base::value; + + bool load(handle src, bool convert) { + return base::template load_impl>>( + src, convert); + } + + explicit operator type *() { return this->value; } + // static_cast works around compiler error with MSVC 17 and CUDA 10.2 + // see issue #2180 + explicit operator type &() { return *(static_cast(this->value)); } + explicit operator std::shared_ptr *() { return std::addressof(holder); } + explicit operator std::shared_ptr &() { return holder; } + + static handle cast(const std::shared_ptr &src, return_value_policy, handle) { + const auto *ptr = holder_helper>::get(src); + return type_caster_base::cast_holder(ptr, &src); + } + +protected: + friend class type_caster_generic; + void check_holder_compat() { + if (typeinfo->default_holder) { + throw cast_error("Unable to load a custom holder type from a default-holder instance"); + } + } + + bool load_value(value_and_holder &&v_h) { + if (v_h.holder_constructed()) { + value = v_h.value_ptr(); + holder = v_h.template holder>(); + return true; + } + throw cast_error("Unable to cast from non-held to held instance (T& to Holder) " +#if !defined(PYBIND11_DETAILED_ERROR_MESSAGES) + "(#define PYBIND11_DETAILED_ERROR_MESSAGES or compile in debug mode for " + "type information)"); +#else + "of type '" + + type_id>() + "''"); +#endif + } + + template , + detail::enable_if_t::value, int> = 0> + bool try_implicit_casts(handle, bool) { + return false; + } + + template , + detail::enable_if_t::value, int> = 0> + bool try_implicit_casts(handle src, bool convert) { + for (auto &cast : typeinfo->implicit_casts) { + copyable_holder_caster sub_caster(*cast.first); + if (sub_caster.load(src, convert)) { + value = cast.second(sub_caster.value); + holder = std::shared_ptr(sub_caster.holder, (type *) value); + return true; + } + } + return false; + } + + static bool try_direct_conversions(handle) { return false; } + + std::shared_ptr holder; +}; + /// Specialize for the common std::shared_ptr, so users don't need to template class type_caster> : public copyable_holder_caster> {}; @@ -847,6 +925,19 @@ struct move_only_holder_caster { static constexpr auto name = type_caster_base::name; }; +// BAKEIN_WIP +template +struct move_only_holder_caster> { + static_assert(std::is_base_of, type_caster>::value, + "Holder classes are only supported for custom types"); + + static handle cast(std::unique_ptr &&src, return_value_policy, handle) { + auto *ptr = src.get(); + return type_caster_base::cast_holder(ptr, std::addressof(src)); + } + static constexpr auto name = type_caster_base::name; +}; + template class type_caster> : public move_only_holder_caster> {};