diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index 8b2983b1e..4256ff6a0 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -867,8 +867,8 @@ template using cast_is_temporary_value_reference = bool_constant !std::is_base_of>::value >; -template make_caster load_type(const handle &handle) { - make_caster conv; +// Basic python -> C++ casting; throws if casting fails +template TypeCaster &load_type(TypeCaster &conv, const handle &handle) { if (!conv.load(handle, true)) { #if defined(NDEBUG) throw cast_error("Unable to cast Python instance to C++ type (compile in debug mode for details)"); @@ -879,6 +879,12 @@ template make_caster load_type(const handle &handle) { } return conv; } +// Wrapper around the above that also constructs and returns a type_caster +template make_caster load_type(const handle &handle) { + make_caster conv; + load_type(conv, handle); + return conv; +} NAMESPACE_END(detail) @@ -943,22 +949,16 @@ template <> inline void object::cast() && { return; } NAMESPACE_BEGIN(detail) -struct overload_nothing {}; // Placeholder type for the unneeded (and dead code) static variable in the OVERLOAD_INT macro -template using overload_local_t = conditional_t< - cast_is_temporary_value_reference::value, intrinsic_t, overload_nothing>; - -template enable_if_t::value, T> storage_cast(intrinsic_t &v) { return v; } -template enable_if_t::value, T> storage_cast(intrinsic_t &v) { return &v; } +struct overload_unused {}; // Placeholder type for the unneeded (and dead code) static variable in the OVERLOAD_INT macro +template using overload_caster_t = conditional_t< + cast_is_temporary_value_reference::value, make_caster, overload_unused>; // Trampoline use: for reference/pointer types to value-converted values, we do a value cast, then // store the result in the given variable. For other types, this is a no-op. -template enable_if_t::value, T> cast_ref(object &&o, intrinsic_t &storage) { - using type_caster = make_caster; - using itype = intrinsic_t; - storage = std::move(load_type(o).operator typename type_caster::template cast_op_type()); - return storage_cast(storage); +template enable_if_t::value, T> cast_ref(object &&o, make_caster &caster) { + return load_type(caster, o).operator typename make_caster::template cast_op_type(); } -template enable_if_t::value, T> cast_ref(object &&, overload_nothing &) { +template enable_if_t::value, T> cast_ref(object &&, overload_unused &) { pybind11_fail("Internal error: cast_ref fallback invoked"); } // Trampoline use: Having a pybind11::cast with an invalid reference type is going to static_assert, even diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 61eec60a1..a71175231 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -1486,10 +1486,10 @@ template function get_overload(const T *this_ptr, const char *name) { pybind11::gil_scoped_acquire gil; \ pybind11::function overload = pybind11::get_overload(static_cast(this), name); \ if (overload) { \ - pybind11::object o = overload(__VA_ARGS__); \ + auto o = overload(__VA_ARGS__); \ if (pybind11::detail::cast_is_temporary_value_reference::value) { \ - static pybind11::detail::overload_local_t local_value; \ - return pybind11::detail::cast_ref(std::move(o), local_value); \ + static pybind11::detail::overload_caster_t caster; \ + return pybind11::detail::cast_ref(std::move(o), caster); \ } \ else return pybind11::detail::cast_safe(std::move(o)); \ } \