mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-25 22:52:01 +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 <memory>
|
||||||
#include <typeindex>
|
#include <typeindex>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#if defined(__has_include)
|
||||||
|
# if __has_include(<version>)
|
||||||
|
# include <version>
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
// #define PYBIND11_STR_LEGACY_PERMISSIVE
|
// #define PYBIND11_STR_LEGACY_PERMISSIVE
|
||||||
// If DEFINED, pybind11::str can hold PyUnicodeObject or PyBytesObject
|
// If DEFINED, pybind11::str can hold PyUnicodeObject or PyBytesObject
|
||||||
@ -870,5 +875,23 @@ public:
|
|||||||
// Forward-declaration; see detail/class.h
|
// Forward-declaration; see detail/class.h
|
||||||
std::string get_fully_qualified_tp_name(PyTypeObject*);
|
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(detail)
|
||||||
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
|
||||||
|
@ -1505,14 +1505,13 @@ private:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
static void init_holder(detail::instance *inst, detail::value_and_holder &v_h,
|
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 */) {
|
const holder_type * /* unused */, const std::enable_shared_from_this<T> * /* dummy */) {
|
||||||
try {
|
|
||||||
auto sh = std::dynamic_pointer_cast<typename holder_type::element_type>(
|
auto sh = std::dynamic_pointer_cast<typename holder_type::element_type>(
|
||||||
v_h.value_ptr<type>()->shared_from_this());
|
detail::try_get_shared_from_this(v_h.value_ptr<type>()));
|
||||||
if (sh) {
|
if (sh) {
|
||||||
new (std::addressof(v_h.holder<holder_type>())) holder_type(std::move(sh));
|
new (std::addressof(v_h.holder<holder_type>())) holder_type(std::move(sh));
|
||||||
v_h.set_holder_constructed();
|
v_h.set_holder_constructed();
|
||||||
}
|
}
|
||||||
} catch (const std::bad_weak_ptr &) {}
|
|
||||||
|
|
||||||
if (!v_h.holder_constructed() && inst->owned) {
|
if (!v_h.holder_constructed() && inst->owned) {
|
||||||
new (std::addressof(v_h.holder<holder_type>())) holder_type(v_h.value_ptr<type>());
|
new (std::addressof(v_h.holder<holder_type>())) holder_type(v_h.value_ptr<type>());
|
||||||
|
Loading…
Reference in New Issue
Block a user