Introducing is_smart_holder_type_caster_base_tag, to keep smart_holder code more disconnected.

parent 593587b2
...@@ -959,6 +959,12 @@ protected: ...@@ -959,6 +959,12 @@ protected:
static Constructor make_move_constructor(...) { return nullptr; } static Constructor make_move_constructor(...) { return nullptr; }
}; };
// Tag to be used as base class, inspected by is_smart_holder_type_caster<T> test.
struct is_smart_holder_type_caster_base_tag {};
template <typename T>
struct is_smart_holder_type_caster;
//DETAIL/SMART_HOLDER_TYPE_CASTERS_H/BEGIN///////////////////////////////////////////////////////// //DETAIL/SMART_HOLDER_TYPE_CASTERS_H/BEGIN/////////////////////////////////////////////////////////
//FWD begin //FWD begin
...@@ -1185,7 +1191,7 @@ public: ...@@ -1185,7 +1191,7 @@ public:
}; };
// clang-format on // clang-format on
struct smart_holder_type_caster_class_hooks { struct smart_holder_type_caster_class_hooks : is_smart_holder_type_caster_base_tag {
static decltype(&modified_type_caster_generic_load_impl::local_load) static decltype(&modified_type_caster_generic_load_impl::local_load)
get_local_load_function_ptr() { get_local_load_function_ptr() {
return &modified_type_caster_generic_load_impl::local_load; return &modified_type_caster_generic_load_impl::local_load;
...@@ -1219,17 +1225,11 @@ struct smart_holder_type_caster_class_hooks { ...@@ -1219,17 +1225,11 @@ struct smart_holder_type_caster_class_hooks {
}; };
template <typename T> template <typename T>
inline bool check_is_smart_holder_type_caster();
template <typename T>
struct smart_holder_type_caster_load { struct smart_holder_type_caster_load {
using holder_type = pybindit::memory::smart_holder; using holder_type = pybindit::memory::smart_holder;
bool load(handle src, bool convert) { bool load(handle src, bool convert) {
if (!check_is_smart_holder_type_caster<T>()) { static_assert(is_smart_holder_type_caster<T>::value, "Internal consistency error.");
throw cast_error(
"Unable to load a smart-pointer type from a non-smart_holder instance.");
}
load_impl = modified_type_caster_generic_load_impl(typeid(T)); load_impl = modified_type_caster_generic_load_impl(typeid(T));
if (!load_impl.load(src, convert)) if (!load_impl.load(src, convert))
return false; return false;
...@@ -1685,6 +1685,13 @@ template <typename type, typename SFINAE = void> class type_caster : public type ...@@ -1685,6 +1685,13 @@ template <typename type, typename SFINAE = void> class type_caster : public type
template <typename type> using make_caster = type_caster<intrinsic_t<type>>; template <typename type> using make_caster = type_caster<intrinsic_t<type>>;
template <typename T>
struct is_smart_holder_type_caster {
static constexpr bool value = std::is_base_of<
is_smart_holder_type_caster_base_tag,
make_caster<T>>::value;
};
// Shortcut for calling a caster's `cast_op_type` cast operator for casting a type_caster to a T // Shortcut for calling a caster's `cast_op_type` cast operator for casting a type_caster to a T
template <typename T> typename make_caster<T>::template cast_op_type<T> cast_op(make_caster<T> &caster) { template <typename T> typename make_caster<T>::template cast_op_type<T> cast_op(make_caster<T> &caster) {
return caster.operator typename make_caster<T>::template cast_op_type<T>(); return caster.operator typename make_caster<T>::template cast_op_type<T>();
...@@ -2452,21 +2459,6 @@ template <typename T> struct move_if_unreferenced<T, enable_if_t<all_of< ...@@ -2452,21 +2459,6 @@ template <typename T> struct move_if_unreferenced<T, enable_if_t<all_of<
>::value>> : std::true_type {}; >::value>> : std::true_type {};
template <typename T> using move_never = none_of<move_always<T>, move_if_unreferenced<T>>; template <typename T> using move_never = none_of<move_always<T>, move_if_unreferenced<T>>;
template <typename T, typename SFINAE = void>
struct is_smart_holder_type_caster : std::false_type {};
template <typename T>
struct is_smart_holder_type_caster<
T,
typename std::enable_if<
std::is_base_of<smart_holder_type_caster_class_hooks, make_caster<T>>::value>::type>
: std::true_type {};
template <typename T>
inline bool check_is_smart_holder_type_caster() {
return is_smart_holder_type_caster<T>::value;
}
// Detect whether returning a `type` from a cast on type's type_caster is going to result in a // Detect whether returning a `type` from a cast on type's type_caster is going to result in a
// reference or pointer to a local variable of the type_caster. Basically, only // reference or pointer to a local variable of the type_caster. Basically, only
// non-reference/pointer `type`s and reference/pointers from a type_caster_generic are safe; // non-reference/pointer `type`s and reference/pointers from a type_caster_generic are safe;
......
...@@ -292,6 +292,18 @@ PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS(ElementBase, std::shared_ptr<ElementB ...@@ -292,6 +292,18 @@ PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS(ElementBase, std::shared_ptr<ElementB
PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS(ElementA, std::shared_ptr<ElementA>) PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS(ElementA, std::shared_ptr<ElementA>)
PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS(ElementList, std::shared_ptr<ElementList>) PYBIND11_SMART_POINTER_HOLDER_TYPE_CASTERS(ElementList, std::shared_ptr<ElementList>)
#ifdef PYBIND11_USE_SMART_HOLDER_AS_DEFAULT
// To prevent triggering a static_assert in the smart_holder code.
// This is a very special case, because the associated test exercises a holder mismatch.
namespace pybind11 {
namespace detail {
template <>
class type_caster<std::shared_ptr<HeldByDefaultHolder>>
: public copyable_holder_caster<HeldByDefaultHolder, std::shared_ptr<HeldByDefaultHolder>> {};
} // namespace detail
} // namespace pybind11
#endif
TEST_SUBMODULE(smart_ptr, m) { TEST_SUBMODULE(smart_ptr, m) {
// test_smart_ptr // test_smart_ptr
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment