Skip to content

Commit 3f2b120

Browse files
committed
Fix private enable_shared_from_this issue (with a lot of help from ChatGPT).
1 parent 27d786e commit 3f2b120

File tree

2 files changed

+15
-1
lines changed

2 files changed

+15
-1
lines changed

include/pybind11/detail/struct_smart_holder.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,23 @@ High-level aspects:
6262
namespace pybindit {
6363
namespace memory {
6464

65+
// Default fallback.
6566
static constexpr bool type_has_shared_from_this(...) { return false; }
6667

68+
// This overload (generated by ChatGPT) uses SFINAE to skip enable_shared_from_this checks when the
69+
// base is inaccessible (e.g. private inheritance).
6770
template <typename T>
68-
static constexpr bool type_has_shared_from_this(const std::enable_shared_from_this<T> *) {
71+
static auto type_has_shared_from_this(const T *ptr)
72+
-> decltype(static_cast<const std::enable_shared_from_this<T> *>(ptr), true) {
6973
return true;
7074
}
7175

76+
// Inaccessible base → substitution failure → fallback overload selected
77+
template <typename T>
78+
static constexpr bool type_has_shared_from_this(const void *) {
79+
return false;
80+
}
81+
7282
struct guarded_delete {
7383
std::weak_ptr<void> released_ptr; // Trick to keep the smart_holder memory footprint small.
7484
std::function<void(void *)> del_fun; // Rare case.

tests/pure_cpp/smart_holder_poc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ namespace pybindit {
1010
namespace memory {
1111
namespace smart_holder_poc { // Proof-of-Concept implementations.
1212

13+
struct PrivateESFT : private std::enable_shared_from_this<PrivateESFT> {};
14+
static_assert(!pybindit::memory::type_has_shared_from_this(static_cast<PrivateESFT *>(nullptr)),
15+
"should detect inaccessible base");
16+
1317
template <typename T>
1418
T &as_lvalue_ref(const smart_holder &hld) {
1519
static const char *context = "as_lvalue_ref";

0 commit comments

Comments
 (0)