Use dynamic cast for shared_from_this holder init

Using a dynamic_cast instead of a static_cast is needed to safely cast
from a base to a derived type.  The previous static_pointer_cast isn't
safe, however, when downcasting (and fails to compile when downcasting
with virtual inheritance).

Switching this to always use a dynamic_pointer_cast shouldn't incur any
additional overhead when a static_pointer_cast is safe (i.e. when
upcasting, or self-casting): compilers don't need RTTI checks in those
cases.
This commit is contained in:
Jason Rhinelander
2017-05-19 13:34:55 -04:00
parent 35998a0314
commit b8ac438386
3 changed files with 23 additions and 6 deletions

View File

@@ -214,6 +214,12 @@ struct SharedFromThisRef {
std::shared_ptr<B> shared = std::make_shared<B>();
};
// Issue #865: shared_from_this doesn't work with virtual inheritance
struct SharedFromThisVBase : std::enable_shared_from_this<SharedFromThisVBase> {
virtual ~SharedFromThisVBase() = default;
};
struct SharedFromThisVirt : virtual SharedFromThisVBase {};
template <typename T>
class CustomUniquePtr {
std::unique_ptr<T> impl;
@@ -258,6 +264,11 @@ test_initializer smart_ptr_and_references([](py::module &pm) {
.def("set_ref", [](SharedFromThisRef &, const B &) { return true; })
.def("set_holder", [](SharedFromThisRef &, std::shared_ptr<B>) { return true; });
// Issue #865: shared_from_this doesn't work with virtual inheritance
static std::shared_ptr<SharedFromThisVirt> sft(new SharedFromThisVirt());
py::class_<SharedFromThisVirt, std::shared_ptr<SharedFromThisVirt>>(m, "SharedFromThisVirt")
.def_static("get", []() { return sft.get(); });
struct C {
C() { print_created(this); }
~C() { print_destroyed(this); }