mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-26 07:02:11 +00:00
Manually picked diffs for cast.h (from remove_cross_extension_shared_state branch)
This commit is contained in:
parent
069faee8fc
commit
a4c5ab4b24
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#include "detail/common.h"
|
#include "detail/common.h"
|
||||||
#include "detail/descr.h"
|
#include "detail/descr.h"
|
||||||
|
#include "detail/native_enum_data.h"
|
||||||
#include "detail/type_caster_base.h"
|
#include "detail/type_caster_base.h"
|
||||||
#include "detail/typeid.h"
|
#include "detail/typeid.h"
|
||||||
#include "pytypes.h"
|
#include "pytypes.h"
|
||||||
@ -53,6 +54,125 @@ cast_op(make_caster<T> &&caster) {
|
|||||||
return std::move(caster).operator result_t();
|
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>
|
template <typename type>
|
||||||
class type_caster<std::reference_wrapper<type>> {
|
class type_caster<std::reference_wrapper<type>> {
|
||||||
private:
|
private:
|
||||||
@ -1422,8 +1542,17 @@ template <typename T,
|
|||||||
= 0>
|
= 0>
|
||||||
T cast(const handle &handle) {
|
T cast(const handle &handle) {
|
||||||
using namespace detail;
|
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");
|
"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));
|
return cast_op<T>(load_type<T>(handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user