c++ - Removing back pointers with the use of explicit instantiation declarations causes std::bad_weak_ptr exception -
i have developed code compiles correctly, fails @ (debug) runtime. using vs2015.
background: building advanced message engine. make programmatic addition of new messages maintainable, in production code took time craft initial messages using explicit initialization declaration
c++ construct. works , makes crafting of new messages cookie-cutter, not mention reducing maintenance of messaging guts nothing. here skeleton code functionality:
#include <memory> template< typename d_t > struct h // prototype explicit initialization declarations (eid) { h( d_t& d ) : x { d } {} d_t& x; }; template< typename d_t > struct b // base class derived objects d1 , d2 { b( d_t& d ) : d { d } {} d_t& d; // kind of backptr initialized when eids contructed // actual eids , b h< d_t > { d }; h< d_t > b { d }; }; struct d1 : public b< d1 > { d1() : b( *this ) {} void func1() {} }; struct d2 : public b< d2 > { d2() : b( *this ) {} void func2() {} }; int main() { d1 d1; d2 d2; // designed either derived object can access either explicitly initialized member or b d1.a.x.func1(); // ok d1.b.x.func1(); // ok d2.a.x.func2(); // ok d2.b.x.func2(); // ok return 0; }
this code compiles , runs.
but derived objects in real code shared ptrs. therefore added functionality code. notice obtaining derived class’es this
ptr using enable_shared_from_this
construct:
#include <memory> template< typename d_t > struct h { h( std::shared_ptr< d_t >& d ) : x { d } {} std::shared_ptr< d_t >& x; }; template< typename d_t > struct b { b( std::shared_ptr< d_t >& d ) : d { d } {} std::shared_ptr< d_t >& d; h< d_t > { d }; // initialized d1 h< d_t > b { d }; }; struct d1: public std::enable_shared_from_this< d1 >, public b< d1 > { d1() : b( shared_from_this() ) {} // runtime error: bad weak prt void func1() {} }; struct d2: public std::enable_shared_from_this< d2 >, public b< d2 > { d2() : b( shared_from_this() ) {} void func2() {} }; int main() { d1 d1; d2 d2; d1.a.x->func1(); d1.b.x->func1(); d2.a.x->func2(); d2.b.x->func2(); return 0; }
this code compiles. however, not run , @ d1 constructor, breaks exception std::bad_weak_ptr.
i have attempted change shared ptrs weak ptrs without success. see problem?
edit 1: per @pat’s observation shared_from_this()
not callable constructor, see modified code below compiles , runs:
#include <memory> template< typename d_t > struct h { h( d_t& d ) : x { d } {} d_t& x; }; template< typename d_t > struct b { b( d_t& d ) : d { d } {} d_t& d; h< d_t > { d }; h< d_t > b { d }; }; struct d1 : public std::enable_shared_from_this< d1 >, public b< d1 > { d1() : b( *this ) {} void func1() {} }; struct d2 : public std::enable_shared_from_this< d1 >, public b< d2 > { d2() : b( *this ) {} void func2() {} }; int main() { d1 d1; d2 d2; d1.a.x.func1(); d1.b.x.func1(); d2.a.x.func2(); d2.b.x.func2(); return 0; }
edit 2: code below re-write of original posting's code , builds on @pat's answer. here changed: explicit instantiation declarations (eid) moved derived classes. b no longer trying reference derived object. plain mistake. weak_ptr pointer replaced simple ptr (as case in prototypes). no problem leaks since derived objects (d1 , d2) own object outright. (in producion code member types shared ptrs prevent leaks.)
#include <memory> #include <cassert> template< typename d_t > struct h { h( d_t* d ) : x { d } {} d_t* x; int qq { 0 }; }; struct b { b() {} int rr { 0 }; }; struct d1 : public b { h< d1 > { }; // explicit instantiation declaration int ss { 0 }; }; struct d2 : public b { h< d2 > b { }; // explicit instantiation declaration int tt { 0 }; }; int main() { d1 d1; d2 d2; d1.rr = 99; d2.b.x->rr = 88; assert( d1.rr == d1.a.x->rr ); // ok assert( d2.rr == d2.b.x->rr ); // ok return 0; }
the design invariant code maintenance complexity reduced exponential (as case in prototypes) linear when adding number of eids has been achieved.
the object has managed shared pointer shared_from_this
work. it's undefined behavior in c++14 call shared_from_this
on object not managed shared_ptr
. so, won't able call shared_from_this
constructor since object won't inside shared_ptr
@ point.
example cppreference...
struct good: std::enable_shared_from_this<good> { std::shared_ptr<good> getptr() { return shared_from_this(); } }; // bad: shared_from_this called without having std::shared_ptr owning caller try { not_so_good; std::shared_ptr<good> gp1 = not_so_good.getptr(); } catch(std::bad_weak_ptr& e) { // undefined behavior (until c++17) , std::bad_weak_ptr thrown (since c++17) std::cout << e.what() << '\n'; }
Comments
Post a Comment