I have an object (Z) which derives from two other objects (A and B).
A and B both derive from enable_shared_from_this<>
, respectively enable
Using the shared_ptr
aliasing constructor, a variation of ecatmur's answer can be derived:
#include <memory>
struct virtual_enable_shared_from_this_base:
std::enable_shared_from_this<virtual_enable_shared_from_this_base> {
virtual ~virtual_enable_shared_from_this_base() {}
};
template<typename T>
struct virtual_enable_shared_from_this:
virtual virtual_enable_shared_from_this_base {
std::shared_ptr<T> shared_from_this() {
return std::shared_ptr<T>(
virtual_enable_shared_from_this_base::shared_from_this(),
static_cast<T*>(this));
}
std::shared_ptr<const T> shared_from_this() const {
return std::shared_ptr<const T>(
virtual_enable_shared_from_this_base::shared_from_this(),
static_cast<const T*>(this));
}
};
struct A: virtual_enable_shared_from_this<A> {};
struct B: virtual_enable_shared_from_this<B> {};
struct Z: A, B { };
int main() {
std::shared_ptr<Z> z = std::make_shared<Z>();
std::shared_ptr<B> b = z->B::shared_from_this();
}
I expect this version to be faster in many circumstances, since it avoids a costly dynamic cast. However, as usual, only becnhmarks have the final word. Also, I have added the const
variation.
Yep, your class will be derived from two distinct classes enable_shared_from_this<A>
and enable_shared_from_this<B>
, and have two different weak ref's
Trick from that answer allows to have one base class, because of virtual inheritance
Yes, as per bad weak pointer when base and derived class both inherit from boost::enable_shared_from_this the solution is to use virtual inheritance. Here's an implementation for the C++11 standard shared_ptr
(not Boost):
#include <memory>
struct virtual_enable_shared_from_this_base:
std::enable_shared_from_this<virtual_enable_shared_from_this_base> {
virtual ~virtual_enable_shared_from_this_base() {}
};
template<typename T>
struct virtual_enable_shared_from_this:
virtual virtual_enable_shared_from_this_base {
std::shared_ptr<T> shared_from_this() {
return std::dynamic_pointer_cast<T>(
virtual_enable_shared_from_this_base::shared_from_this());
}
};
struct A: virtual_enable_shared_from_this<A> {};
struct B: virtual_enable_shared_from_this<B> {};
struct Z: A, B { };
int main() {
std::shared_ptr<Z> z = std::make_shared<Z>();
std::shared_ptr<B> b = z->B::shared_from_this();
}
This isn't part of the default implementation, probably because of the overhead of virtual inheritance.