El ene. 5, 2017, a las 10:02, Roberto Hinz
escribió: On Thu, Jan 5, 2017 at 1:13 PM, Boris Rasin
mailto:boris@pointx.org> wrote: Here is how I fixed multiple inheritance problem:
template <typename T> class virtual_shared_from_this : public virtual std::enable_shared_from_this<void> { public: std::shared_ptr<T> shared_from_this() { return std::shared_ptr<T>(std::enable_shared_from_this<void>::shared_from_this(), static_cast
(this)); } }; You use virtual_shared_from_this exactly as you would use enable_shared_from_this. It supports multiple inheritance and is very efficient (no use of dynamic_cast).
This indeed solves the problem of multiple inheritance. But I think I didn't expose well enough the other problem, which has to do with cyclic references:
Suppose an object A has a shared_ptr to an object B which has a weak_ptr to A. Every time this weak_ptr is used, it may not be eligible anymore to originate a non null shared_ptr. In this case, if B can nicely handle this locally ( checking the result of weak_ptr
::lock() ), then fine. But if it can't, is has to throw an exception. And this can be highly undesirable. One way to solve this problem would turn B a member object of A, or manage B with a unique_ptr owned by A. This way we ensure that A is never destroyed before B. But suppose that for some reason, there is something that requires a shared_ptr to B. How do you solve that?
For this exact scenario, you can use the aliasing constructor of shared_ptr (for reference, see constructor #8 on http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr): class A : public std::enable_shared_from_this<A> { // ... protected: std::shared_ptr<B> make_B_handle() const { return std::shared_ptr<B>{ shared_from_this(), b_.get() }; } private: std::unique_ptr<B> b_; }; The aliasing constructor says roughly that "I know that the pointer I'm giving you (the B* in this case) is valid if and only if the shared_ptr<A> is valid". You could even have the B directly in the A instead of via a unique_ptr (and then you give &b_ instead of b_.get()).
I have to agree that this is a very specific situation. But when it happens, it seems that it can only be solved with shared_handle ( or with enable_shared_from_raw which has no doc and I didn't know exists until now ).
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost http://lists.boost.org/mailman/listinfo.cgi/boost