c++ - Unable to move temporary object into the *this object -


while trying create binary search tree (bst) using c++11 hit snag. can't extract created bst out of function created. function reads data file (in case number on each line) , builds bst those. building part in loop works correctly. problem can't temporary object moved want be.

zooming in on problem think, see edit 3.

more context: bst<t> class derives publicly std::unique_ptr<bstknoop<t>>
bst<t> inherits constructors of unique_ptr<bstknoop<t>> with

template<class t> using bstknoopptr=std::unique_ptr<bstknoop<t>>; // alias template 

and

using bstknoopptr<t>::bstknoopptr; // in body of bst<t> class declaration` 

a bstknoop<t> data structure 3 fields 1 t object hold node data 2 bst<t> objects left , right (each child tree in own right)

the goal move newly created bst calling object. idea in main can call bst<int> tree; tree.lees(ifs); (with ifs open input filestream) , tree holds filled bst afterwards.

the function:

template<class t> istream& bst<t>::lees(istream& is){     string lijn;     t knoopwaarde;     getline(is,lijn);     knoopwaarde = stoi(lijn);     bst<t> temptree(new bstknoop<t>());     temptree->sl = knoopwaarde;      for(int i=1; i<data_set_length ; i++){         getline(is,lijn);         knoopwaarde=stoi(lijn);         temptree.add(knoopwaarde);         cout<<temptree;     }     this->swap(temptree);   /* not work */      /* *this = move(temptree);   not work either*/     return is; } 

i have tried return bst<t> function , moving result in main. didn't work either.

the program crashes @ runtime unknown signal.

side note: i'm unsure why bst<t> temptree(new bstknoop<t>()); works in regard templating. construction works because bst<t> inherits constructors unique_ptr<bstknoop<t>>

edit 1: declaration of bst<t> class:

template <class t> class bst:public bstknoopptr<t>{     using bstknoopptr<t>::bstknoopptr; public:     friend istream& operator>>(istream& is, bst<t>& bb){         return bb.lees(is);     }     friend ostream& operator<<(ostream& os, const bst<t>& bb){         //return bb.schrijflevelorder(os);         return bb.schrijfknoop(os);     }     void add(const t&);     ostream& schrijf(ostream&);     ostream& schrijfknoop(ostream&) const;     int aantalsleutels() const;     istream& lees(istream&);        ostream& schrijflevelorder(ostream& os) const; private: }; 

the declaration of thebstknoop<t> class:

template <class t> class bstknoop{     friend class bst<t>; public:     bstknoop() {}     explicit bstknoop(t _sl) : sl(_sl) {} private:     t sl;     bst<t> links,rechts; }; 

edit 2: i've written move constructor , move assignment operator. i've made sure retain default constructor using bst<t>()=default; i'm confused though: bst class doesn't have members have implement own move constr / operator.
however, bst has inherited unique_ptr<bstknoop<t>>so implicitly, must hold member of type. suppose want keep inheritance, there neat way make work? is true can't (or perhaps shouldn't) implement copy constr / operator deleted unique_ptr?

  template<class t> bst<t>::bst(bst<t>&& other){     *this = move(other); }  template<class t> bst<t>& bst<t>::operator=(bst<t>&& other){     cout<<"called move operator bst"<<endl;     (*this).bstknoopptr<t>::operator=(move(other));     return *this; } 

edit 3: own move constr / operator, temptree no longer gets filled properly. below code add used build tree. if omit own move constr / operator, works. need operation works this->get()->links = move(tmp). types this->get()->links => bst<t> tmp => bst<t> how come works? operation need, why can't use similar *this = move(temptree) writing operation myself.

template<class t> void bst<t>::add(const t& value){     if(value <= this->get()->sl){         if(this->get()->links != nullptr){             this->get()->links.add(value);         }         else {             bst<t> tmp(new bstknoop<t>(value));             this->get()->links = move(tmp);         }     }     else{         if(this->get()->rechts != nullptr){             this->get()->rechts.add(value);         }         else{             bst<t> tmp(new bstknoop<t>(value));             this->get()->rechts = move(tmp);         }     } } 

okay, made stupidest mistake. there nothing wrong inheritance , accompanying move semantics. used data_set_length preprocessor directive inside istream& bst<t>::lees(istream& is) function. while final dataset hold million items. dataset testing purposes holds 12. forgot change value of data_set_length stoi(lijn) crashed.

for interested in solution:

notes

  • you don't need write code make work.
  • it possible write bst<t>& operator=(bstknoopptr<t>&&); , works. without explicitly writing own works.
  • the bst class has no fields of pointer type don't trouble unique_ptr not having virtual destructor

final question (perhaps can comment): inherited operator operator=(bstknoopptr<t>&&), signature in bst<t>? in regards return type (if it's member of bst<t> type return?).

** tldr: why can rely on inherited move operator / move constructors of unique_ptr<bstknoop<t>>? **

bst.h

 #define data_set_length 12  using namespace std;  template <class t> class bst;  template <class t> class bstknoop;  template<class t> using bstknoopptr=std::unique_ptr<bstknoop<t>>;    template <class t> class bst:public bstknoopptr<t>{     using bstknoopptr<t>::bstknoopptr; public:     bst<t>& operator=(bst<t>&&) = default;     bst<t>(bst<t>&&) = default;     bst<t>()=default;     //bst<t>& operator=(bstknoopptr<t>&&);      friend istream& operator>>(istream& is, bst<t>& bb){         return bb.lees(is);     }     friend ostream& operator<<(ostream& os, const bst<t>& bb){         //return bb.schrijflevelorder(os);         return bb.schrijfknoop(os);     }     void add(const t&); //schrijf schrijft uit in een vorm die min of meer menselijk leesbaar     ostream& schrijf(ostream&);     ostream& schrijfknoop(ostream&) const;     int aantalsleutels() const;     istream& lees(istream&); //schrijflevelorder schrijft uit in een vorm die door lees(...) kan gelezen worden.     ostream& schrijflevelorder(ostream& os) const; private: };  template <class t> class bstknoop{     friend class bst<t>; public:     bstknoop() {}     explicit bstknoop(t _sl) : sl(_sl) {} private:     t sl;     bst<t> links,rechts; };   //template<class t> //bst<t>& bst<t>::operator=(bstknoopptr<t>&& other){ //    cout<<"called bst<t> move bstknoopptr r-value ref argument"<<endl; //    (*this).bstknoopptr<t>::operator=(move(other)); //    return *this; //}   template<class t> void bst<t>::add(const t& value){     if(value <= this->get()->sl){         if(this->get()->links != nullptr){             this->get()->links.add(value);         }         else {             //bstknoopptr<t> tmp(new bstknoop<t>(value)); if used own bst<t>& bst<t>::operator=(bstknoopptr<t>&& other)             bst<t> tmp(new bstknoop<t>(value));             this->get()->links = move(tmp);         }     }     else{         if(this->get()->rechts != nullptr){             this->get()->rechts.add(value);         }         else{             //bstknoopptr<t> tmp(new bstknoop<t>(value)); if used own bst<t>& bst<t>::operator=(bstknoopptr<t>&& other)             bst<t> tmp(new bstknoop<t>(value));             this->get()->rechts = move(tmp);         }     } }  template<class t> istream& bst<t>::lees(istream& is){     string lijn;     t knoopwaarde;     getline(is,lijn);     knoopwaarde = stoi(lijn);     bst<t> temptree(new bstknoop<t>());     temptree->sl = knoopwaarde;      for(int i=1; i<data_set_length ; i++){         getline(is,lijn);         knoopwaarde=stoi(lijn);         temptree.add(knoopwaarde);         cout<<temptree;     }     *this = move(temptree);     return is; } 

main.cpp

int main(){     ifstream ifs;     ifs.open("c.dat");     if(ifs.is_open()){         bst<int> tree;         tree.lees(ifs);                 tree.schrijfknoop(cout);      }     else {         cerr<<"failed open file"<<endl;         return -1;     } } 

Comments

Popular posts from this blog

android - InAppBilling registering BroadcastReceiver in AndroidManifest -

python Tkinter Capturing keyboard events save as one single string -

sql server - Why does Linq-to-SQL add unnecessary COUNT()? -