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

Popular posts from this blog

account - Script error login visual studio DefaultLogin_PCore.js -

xcode - CocoaPod Storyboard error: -