Double inheritance of enable_shared_from_this
Solution 1
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.
Solution 2
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
Offirmo
~12 years of experience in web development in javascript / html / css, big enterprise apps in C++ and embedded network devices in C. Mostly interested in web app development, javascript, Python, C++... SOreadytohelp !
Updated on June 15, 2022Comments
-
Offirmo almost 2 years
I have an object (Z) which derives from two other objects (A and B).
A and B both derive from
enable_shared_from_this<>
, respectivelyenable_shared_from_this<A>
andenable_shared_from_this<B>
.Of course I call
shared_from_this()
on Z. And of course the compiler reports this as ambiguous.My questions are :
- is it safe to inherit twice from
enable_shared_from_this<>
or will it create two separated reference counts (bad !) - If not safe, how do I solve this ?
Note : I've found this other question bad weak pointer when base and derived class both inherit from boost::enable_shared_from_this but it doesn't really answer. Should I use the
virtual
trick too ?-
user about 10 yearspossible duplicate of boost shared_from_this and multiple inheritance
- is it safe to inherit twice from
-
Offirmo about 11 yearsWhy isn't this trick integrated in
enable_shared_from_this
by default ? -
kassak about 11 years@LucDanton It can not deal, because both instatiations of enable shared from this are distinct classes. That is why even vrtually inherited they are distinct. The only way is to have one virtual class, which inherits it with any type argument, and then use that virtual class as base. The only problem can be, in
make_shared
but I'm not sure -
Offirmo about 11 years@LucDanton thinking about it, using the "virtual" trick force the derived object to have a virtual table, thus making it bigger. Since C++ philosophy is "you only pay for what you ask", the virtual trick should not be used by default.
-
ecatmur about 11 years@kassak
static_pointer_cast
won't work; this is virtual inheritance so a dynamic cast is required. -
kassak about 11 yearsbut that is simple downcasting from
virtual_enable_shared_from_this_base
toT
, derived from it. Compiler complains? -
ecatmur about 11 years@kassak yes:
cannot convert from base 'virtual_enable_shared_from_this_base' to derived type 'B' via virtual base 'virtual_enable_shared_from_this_base'
-
Luc Danton about 11 yearsIt may not be the best to mention
std::enable_shared_from_this
. From what I can tell of the requirements, not using virtual inheritance is still supposed to work (which might be a defect). -
Luc Danton about 11 yearsI made the mistake of thinking that this question was specifically about C++11 and
std::enable_shared_from_this
, apologies. -
curiousguy over 4 yearsVirtual inheritance, like virtual functions, is much less efficient; it generates larger classes, larger vtables, and unreliable code in corner cases. It's very easy to get UB when using virtual bases during construction (arguably not a problem here as that base obviously can't be used during construction).
-
arsdever about 4 yearsWhy not to simply virtually derive from
enable_from_this
? Can you explain to me? -
ecatmur about 4 years@arsdever
enable_shared_from_this
is a template, so the two virtual base clases would be different and virtual inheritance wouldn't accomplish anything.