Manually picked diffs for cast.h (from remove_cross_extension_shared_state branch)

This commit is contained in:
Ralf W. Grosse-Kunstleve 2024-07-31 14:06:39 -07:00
parent 069faee8fc
commit a4c5ab4b24

View File

@ -12,6 +12,7 @@
#include "detail/common.h"
#include "detail/descr.h"
#include "detail/native_enum_data.h"
#include "detail/type_caster_base.h"
#include "detail/typeid.h"
#include "pytypes.h"
@ -53,6 +54,125 @@ cast_op(make_caster<T> &&caster) {
return std::move(caster).operator result_t();
}
template <typename EnumType>
class type_caster_enum_type {
private:
using Underlying = typename std::underlying_type<EnumType>::type;
public:
static constexpr auto name = const_name<EnumType>();
template <typename SrcType>
static handle cast(SrcType &&src, return_value_policy, handle parent) {
handle native_enum
= global_internals_native_enum_type_map_get_item(std::type_index(typeid(EnumType)));
if (native_enum) {
return native_enum(static_cast<Underlying>(src)).release();
}
return type_caster_for_class_<EnumType>::cast(
std::forward<SrcType>(src),
// Fixes https://github.com/pybind/pybind11/pull/3643#issuecomment-1022987818:
return_value_policy::copy,
parent);
}
bool load(handle src, bool convert) {
handle native_enum
= global_internals_native_enum_type_map_get_item(std::type_index(typeid(EnumType)));
if (native_enum) {
if (!isinstance(src, native_enum)) {
return false;
}
type_caster<Underlying> underlying_caster;
if (!underlying_caster.load(src.attr("value"), convert)) {
pybind11_fail("native_enum internal consistency failure.");
}
value = static_cast<EnumType>(static_cast<Underlying>(underlying_caster));
return true;
}
if (!pybind11_enum_) {
pybind11_enum_.reset(new type_caster_for_class_<EnumType>());
}
return pybind11_enum_->load(src, convert);
}
template <typename T>
using cast_op_type = detail::cast_op_type<T>;
// NOLINTNEXTLINE(google-explicit-constructor)
operator EnumType *() {
if (!pybind11_enum_) {
return &value;
}
return pybind11_enum_->operator EnumType *();
}
// NOLINTNEXTLINE(google-explicit-constructor)
operator EnumType &() {
if (!pybind11_enum_) {
return value;
}
return pybind11_enum_->operator EnumType &();
}
private:
std::unique_ptr<type_caster_for_class_<EnumType>> pybind11_enum_;
EnumType value;
};
template <typename EnumType, typename SFINAE = void>
struct type_caster_enum_type_enabled : std::true_type {};
template <typename T>
struct type_uses_type_caster_enum_type {
static constexpr bool value
= std::is_enum<T>::value && type_caster_enum_type_enabled<T>::value;
};
template <typename EnumType>
class type_caster<EnumType, detail::enable_if_t<type_uses_type_caster_enum_type<EnumType>::value>>
: public type_caster_enum_type<EnumType> {};
template <typename T>
struct type_uses_smart_holder_type_caster {
static constexpr bool value
= std::is_base_of<smart_holder_type_caster_base_tag, make_caster<T>>::value
#ifdef PYBIND11_USE_SMART_HOLDER_AS_DEFAULT
|| type_uses_type_caster_enum_type<T>::value
#endif
;
};
template <typename T, typename SFINAE = void>
struct type_caster_classh_enum_aware : type_caster<T> {};
#ifdef PYBIND11_USE_SMART_HOLDER_AS_DEFAULT
template <typename EnumType>
struct type_caster_classh_enum_aware<
EnumType,
detail::enable_if_t<type_uses_type_caster_enum_type<EnumType>::value>>
: type_caster_for_class_<EnumType> {};
#endif
template <typename T, detail::enable_if_t<std::is_enum<T>::value, int> = 0>
bool isinstance_native_enum_impl(handle obj, const std::type_info &tp) {
handle native_enum = global_internals_native_enum_type_map_get_item(tp);
if (!native_enum) {
return false;
}
return isinstance(obj, native_enum);
}
template <typename T, detail::enable_if_t<!std::is_enum<T>::value, int> = 0>
bool isinstance_native_enum_impl(handle, const std::type_info &) {
return false;
}
template <typename T>
bool isinstance_native_enum(handle obj, const std::type_info &tp) {
return isinstance_native_enum_impl<intrinsic_t<T>>(obj, tp);
}
template <typename type>
class type_caster<std::reference_wrapper<type>> {
private:
@ -1422,8 +1542,17 @@ template <typename T,
= 0>
T cast(const handle &handle) {
using namespace detail;
static_assert(!cast_is_temporary_value_reference<T>::value,
constexpr bool is_enum_cast = type_uses_type_caster_enum_type<intrinsic_t<T>>::value;
static_assert(!cast_is_temporary_value_reference<T>::value || is_enum_cast,
"Unable to cast type to reference: value is local to type caster");
#ifndef NDEBUG
if (is_enum_cast && cast_is_temporary_value_reference<T>::value) {
if (detail::global_internals_native_enum_type_map_contains(
std::type_index(typeid(intrinsic_t<T>)))) {
pybind11_fail("Unable to cast native enum type to reference");
}
}
#endif
return cast_op<T>(load_type<T>(handle));
}