mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
When determining if a shared_ptr already exists, use a test on the we… (#2819)
* When determining if a shared_ptr already exists, use a test on the weak_ptr instead of a try/catch block. * When determining if a shared_ptr already exists, use a test on the weak_ptr instead of a try/catch block. * weak_from_this is only available in C++17 and later * Switch to use feature flag instead of C++ version flag. * Add Microsoft-specific check. * Avoid undefined preprocessor macro warning treated as error. * Simplify shared_from_this in init_holder * Include <version> in detail/common.h (~stolen~ borrowed from @bstaletic's #2816) * Move class_::get_shared_from_this to detail::try_get_shared_from_this * Simplify try_get_shared_from_this by using weak_ptr::lock() Co-authored-by: Yannick Jadoul <yannick.jadoul@belgacom.net>
This commit is contained in:
parent
0432ae7c52
commit
23c3edcf21
@ -162,6 +162,11 @@
|
||||
#include <memory>
|
||||
#include <typeindex>
|
||||
#include <type_traits>
|
||||
#if defined(__has_include)
|
||||
# if __has_include(<version>)
|
||||
# include <version>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// #define PYBIND11_STR_LEGACY_PERMISSIVE
|
||||
// If DEFINED, pybind11::str can hold PyUnicodeObject or PyBytesObject
|
||||
@ -870,5 +875,23 @@ public:
|
||||
// Forward-declaration; see detail/class.h
|
||||
std::string get_fully_qualified_tp_name(PyTypeObject*);
|
||||
|
||||
template <typename T>
|
||||
inline static std::shared_ptr<T> try_get_shared_from_this(std::enable_shared_from_this<T> *holder_value_ptr) {
|
||||
// Pre C++17, this code path exploits undefined behavior, but is known to work on many platforms.
|
||||
// Use at your own risk!
|
||||
// See also https://en.cppreference.com/w/cpp/memory/enable_shared_from_this, and in particular
|
||||
// the `std::shared_ptr<Good> gp1 = not_so_good.getptr();` and `try`-`catch` parts of the example.
|
||||
#if defined(__cpp_lib_enable_shared_from_this) && (!defined(_MSC_VER) || _MSC_VER >= 1912)
|
||||
return holder_value_ptr->weak_from_this().lock();
|
||||
#else
|
||||
try {
|
||||
return holder_value_ptr->shared_from_this();
|
||||
}
|
||||
catch (const std::bad_weak_ptr &) {
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
PYBIND11_NAMESPACE_END(detail)
|
||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||
|
@ -1505,14 +1505,13 @@ private:
|
||||
template <typename T>
|
||||
static void init_holder(detail::instance *inst, detail::value_and_holder &v_h,
|
||||
const holder_type * /* unused */, const std::enable_shared_from_this<T> * /* dummy */) {
|
||||
try {
|
||||
auto sh = std::dynamic_pointer_cast<typename holder_type::element_type>(
|
||||
v_h.value_ptr<type>()->shared_from_this());
|
||||
if (sh) {
|
||||
new (std::addressof(v_h.holder<holder_type>())) holder_type(std::move(sh));
|
||||
v_h.set_holder_constructed();
|
||||
}
|
||||
} catch (const std::bad_weak_ptr &) {}
|
||||
|
||||
auto sh = std::dynamic_pointer_cast<typename holder_type::element_type>(
|
||||
detail::try_get_shared_from_this(v_h.value_ptr<type>()));
|
||||
if (sh) {
|
||||
new (std::addressof(v_h.holder<holder_type>())) holder_type(std::move(sh));
|
||||
v_h.set_holder_constructed();
|
||||
}
|
||||
|
||||
if (!v_h.holder_constructed() && inst->owned) {
|
||||
new (std::addressof(v_h.holder<holder_type>())) holder_type(v_h.value_ptr<type>());
|
||||
|
Loading…
Reference in New Issue
Block a user