Changeset 4069


Ignore:
Timestamp:
Aug 6, 2021, 12:02:23 PM (11 months ago)
Author:
Peter
Message:

implement copy and move constructors/assignment

Location:
branches/kendall-score
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • branches/kendall-score/test/ranking.cc

    r4064 r4069  
    3333void test1(test::Suite& suite)
    3434{
     35  suite.out() << YAT_TEST_PROLOGUE;
    3536  suite.out() << "Constructor(0)\n";
    3637  utility::Ranking<double> ranking;
     
    120121void test2(test::Suite& suite)
    121122{
    122   suite.out() << "=== " << __func__ << " ===\n";
     123  suite.out() << YAT_TEST_PROLOGUE;
    123124  // mimick how Ranking is used in Kendall::score
    124125  utility::Ranking<double> ranking;
     
    169170
    170171
     172void test_copy(test::Suite& suite)
     173{
     174  suite.out() << YAT_TEST_PROLOGUE;
     175  utility::Ranking<double> ranking;
     176  ranking.insert(0);
     177  ranking.insert(1);
     178  ranking.insert(-1);
     179
     180  suite.out() << "test copy constructor\n";
     181  utility::Ranking<double> ranking2(ranking);
     182  int n = std::distance(ranking.begin(), ranking.end());
     183  if (n != 3) {
     184    suite.add(false);
     185    suite.err() << "ranking distance: " << n << "\n";
     186  }
     187
     188  n = std::distance(ranking2.begin(), ranking2.end());
     189  if (n != 3) {
     190    suite.add(false);
     191    suite.err() << "error: copy constructor failed\n";
     192    suite.err() << "ranking2 distance: " << n << "\n";
     193    for (auto it = ranking2.cbegin(); it!=ranking2.cend(); ++it)
     194      suite.err() << "value: " << *it << "\n";
     195  }
     196
     197  utility::Ranking<double> ranking3;
     198  ranking3.insert(10);
     199  suite.out() << "test copy assignment\n";
     200  ranking3 = ranking2;
     201  n = std::distance(ranking3.begin(), ranking3.end());
     202  if (n != 3) {
     203    suite.add(false);
     204    suite.err() << "error: assignment failed\n";
     205    suite.err() << "ranking3 distance: " << n << "\n";
     206  }
     207
     208  suite.out() << "test move constructor\n";
     209  utility::Ranking<double> ranking4(std::move(ranking3));
     210  n = std::distance(ranking4.begin(), ranking4.end());
     211  if (n != 3) {
     212    suite.add(false);
     213    suite.err() << "error: move constructor failed\n";
     214    suite.err() << "ranking4 distance: " << n << "\n";
     215  }
     216
     217  suite.out() << "test move assignment\n";
     218  ranking4 = std::move(ranking2);
     219  n = std::distance(ranking4.begin(), ranking4.end());
     220  if (n != 3) {
     221    suite.add(false);
     222    suite.err() << "error: move assignment failed\n";
     223    suite.err() << "ranking4 distance: " << n << "\n";
     224  }
     225}
     226
     227
    171228int main(int argc, char* argv[])
    172229{
     
    175232    test1(suite);
    176233    test2(suite);
     234    test_copy(suite);
    177235  }
    178236  catch (std::exception& e) {
  • branches/kendall-score/yat/utility/Ranking.h

    r4065 r4069  
    3434#include <memory>
    3535
     36#include <iostream> // debug
    3637namespace theplu {
    3738namespace yat {
     
    7980       \brief Copy constructor
    8081     */
    81     Ranking(const Ranking& other)
    82       : compare_(other.compare())
    83     {
    84       if (!other.empty())
    85         impl_.head_.parent_ = copy(other);
    86     }
     82    Ranking(const Ranking& other);
    8783
    8884    /**
    8985       \brief move constructor
    9086     */
    91     Ranking(Ranking&& other) = default;
     87    Ranking(Ranking&& other);
    9288
    9389    /**
     
    330326    ranking::Impl impl_;
    331327
     328    void clear(void)
     329    {
     330      if (size()) {
     331        YAT_ASSERT(first_node() != &impl_.head_);
     332        erase(first_node());
     333      }
     334      impl_.reset();
     335    }
     336
     337    // return a copy of x but with children and parent set to nullptr.
    332338    ranking::NodeValue<T>*
    333     clone_node(const ranking::NodeValue<T>* x) const
    334     {
    335       YAT_ASSERT(0 && "implement me");
    336       YAT_ASSERT(x);
    337       ranking::NodeValue<T>* tmp = new ranking::NodeValue<T>(*x);
    338       tmp->left_ = nullptr;
    339       tmp->right_ = nullptr;
    340       return tmp;
    341     }
    342 
    343 
    344     ranking::NodeValue<T>* copy(const Ranking& other)
    345     {
    346       YAT_ASSERT(0 && "implement me");
    347       ranking::NodeValue<T>* root = copy(other.first_node(), last_node());
    348       //impl_.left_ = root->left_most();
    349       //impl_.right_ = root->right_most();
    350       //size_ = other.size_;
    351       return root;
    352     }
    353 
    354 
     339    clone_node(const ranking::NodeValue<T>* x) const;
     340
     341    /**
     342       copy data in other.Impl_ into impl_
     343
     344       Basically copy constructor of Impl but nodes (except for head
     345       node) are copied as NodeValue<T> and Impl is not aware of T.
     346     */
     347    ranking::NodeValue<T>* copy(const Ranking& other);
     348
     349    /**
     350       Create a copy of root and return it
     351     */
    355352    ranking::NodeValue<T>*
    356     copy(const ranking::NodeValue<T>* x, ranking::NodeBase* p)
    357     {
    358       YAT_ASSERT(0 && "implement me");
    359       ranking::NodeValue<T>* top = clone_node(x);
    360       top->parent_ = p;
    361       try {
    362         if (x->right_)
    363           top->right_ = copy(right(x), top);
    364         p = top;
    365         x = left(x);
    366         while (x != 0) {
    367           ranking::NodeValue<T>* y = clone_node(x);
    368           p->left_ = y;
    369           y->parent_ = p;
    370           if (x->right_)
    371             y->right_ = copy(right(x), y);
    372           p = y;
    373           x = left(x);
    374         }
    375       }
    376       catch (std::exception& e) {
    377         // cleanup
    378         erase(top);
    379         std::rethrow_exception(std::current_exception());
    380       }
    381       return top;
    382     }
     353    copy(const ranking::NodeValue<T>* root, ranking::NodeBase* h) const;
    383354
    384355
     
    443414
    444415    // delete x and its offsprings
    445     void erase(ranking::NodeValue<T>* x)
    446     {
    447       YAT_ASSERT(0 && "implement me");
     416    void erase(ranking::NodeValue<T>* x) const
     417    {
    448418      while (x) {
    449         erase(right(x));
     419        if (x->right_ && x->right_ !=  &impl_.head_)
     420          erase(right(x));
    450421        ranking::NodeValue<T>* tmp = left(x);
    451422        delete x;
     
    533504
    534505
    535     iterator insert(std::unique_ptr<ranking::NodeValue<T>>&& element,
    536                     ranking::NodeBase* parent, ranking::NodeBase*& child)
    537     {
    538       YAT_ASSERT(0 && "implement me");
    539       YAT_ASSERT(parent);
    540       YAT_ASSERT(child==parent->left_ || child==parent->right_);
    541       // if child is null, assign element
    542       if (!child) {
    543         child = element.release();
    544         child->parent_ = parent;
    545         YAT_ASSERT(child==parent->left_ || child==parent->right_);
    546         ++impl_.node_count_;
    547         return iterator(child);
    548       }
    549       if (compare_(element->value(),
    550                    static_cast<ranking::NodeValue<T>*>(child)->value()))
    551         return insert(std::move(element), child, child->left_);
    552       return insert(std::move(element), child, child->right_);
    553     }
    554 
    555 
    556506    const_iterator
    557507    lower_bound(const ranking::NodeValue<T>* x, const ranking::NodeBase* y,
     
    589539    const ranking::NodeBase* const root_node(void) const
    590540    {
    591       YAT_ASSERT(0 && "implement me");
    592541      return impl_.head_.parent_;
    593542    }
     
    604553      return impl_.head_.left_;
    605554    }
     555
     556
     557    const ranking::NodeValue<T>* parent(const ranking::NodeBase* x) const
     558    {
     559      YAT_ASSERT(x);
     560      YAT_ASSERT(x->parent_);
     561      YAT_ASSERT(x->parent_ != &impl_.head_);
     562      return static_cast<const ranking::NodeValue<T>*>(x->parent_);
     563    }
     564
     565
     566    ranking::NodeValue<T>* parent(ranking::NodeBase* x) const
     567    {
     568      YAT_ASSERT(x);
     569      YAT_ASSERT(x->parent_);
     570      YAT_ASSERT(x->parent_ != &impl_.head_);
     571      return static_cast<ranking::NodeValue<T>*>(x->parent_);
     572    }
     573
    606574
    607575    /*
     
    648616      return true;
    649617#endif
    650 
    651     }
    652 
     618    }
    653619  };
     620
     621
     622  // implementations
     623  template<typename T, typename Compare>
     624  Ranking<T,Compare>::Ranking(const Ranking& other)
     625    : compare_(other.compare())
     626  {
     627    if (!other.empty())
     628      root_node() = copy(other);
     629    YAT_ASSERT(validate());
     630  }
     631
     632
     633  template<typename T, typename Compare>
     634  Ranking<T,Compare>::Ranking(Ranking&& other)
     635    : compare_(std::move(other.compare())), impl_(std::move(other.impl_))
     636  {
     637    YAT_ASSERT(validate());
     638  }
     639
     640
     641  template<typename T, typename Compare>
     642  Ranking<T, Compare>&
     643  Ranking<T, Compare>::operator=(const Ranking& other)
     644  {
     645    if (this != &other) {
     646      Ranking tmp(other);
     647      *this = std::move(tmp);
     648    }
     649    return *this;
     650  }
     651
     652
     653  template<typename T, typename Compare>
     654  Ranking<T, Compare>&
     655  Ranking<T, Compare>::operator=(Ranking&& other)
     656  {
     657    clear();
     658    compare_ = std::move(other.compare_);
     659    impl_ = std::move(other.impl_);
     660    return *this;
     661  }
     662
     663
     664  template<typename T, typename Compare>
     665  ranking::NodeValue<T>* Ranking<T,Compare>::copy(const Ranking& other)
     666  {
     667    YAT_ASSERT(validate());
     668    YAT_ASSERT(impl_.head_.parent_ == nullptr);
     669    YAT_ASSERT(other.first_node());
     670    ranking::NodeValue<T>* root = copy(other.first_node(), last_node());
     671    root->parent_ = nullptr;
     672    root->right_ = last_node();
     673    last_node()->left_ = root->left_most();
     674    last_node()->parent_ = root;
     675    impl_.node_count_ = other.size();
     676    YAT_ASSERT(validate());
     677    return root;
     678  }
     679
     680
     681  template<typename T, typename Compare>
     682  ranking::NodeValue<T>*
     683  Ranking<T,Compare>::copy(const ranking::NodeValue<T>* x,
     684                           ranking::NodeBase* parent) const
     685  {
     686    YAT_ASSERT(x);
     687    ranking::NodeValue<T>* root = clone_node(x);
     688    YAT_ASSERT(root);
     689    root->parent_ = parent;
     690    try {
     691      if (x->right_ && !x->right_->is_head_node()) {
     692        YAT_ASSERT(x != right(x));
     693        YAT_ASSERT(x->right_ != &impl_.head_);
     694        root->right_ = copy(right(x), root);
     695      }
     696
     697      parent = root;
     698      x = left(x);
     699      while (x) {
     700        ranking::NodeValue<T>* y = clone_node(x);
     701        parent->left_ = y;
     702        y->parent_ = parent;
     703        if (x->right_) {
     704          YAT_ASSERT(x->right_ != &impl_.head_);
     705          y->right_ = copy(right(x), y);
     706        }
     707        parent = y;
     708        x = left(x);
     709      }
     710    }
     711    catch (std::exception& e) {
     712      erase(root);
     713      std::rethrow_exception(std::current_exception());
     714    }
     715
     716    return root;
     717  }
     718
     719
     720  template<typename T, typename Compare>
     721  ranking::NodeValue<T>*
     722  Ranking<T,Compare>::clone_node(const ranking::NodeValue<T>* x) const
     723  {
     724    YAT_ASSERT(x);
     725    ranking::NodeValue<T>* res = new ranking::NodeValue<T>(x->value());
     726    res->left_ = nullptr;
     727    res->right_ = nullptr;
     728    res->parent_ = nullptr;
     729    return res;
     730  }
    654731
    655732}}} // of namespace utility, yat, and theplu
  • branches/kendall-score/yat/utility/ranking/Impl.cc

    r4064 r4069  
    3939
    4040
    41   Impl::Impl(Impl&& other)
     41  Impl::Impl(Impl&& from)
    4242  {
    43     assert(0 && "implement me");
    44     if (other.head_.parent_ == nullptr)
    45       reset();
    46     else
    47       move_data(std::move(other));
     43    reset();
     44    if (from.head_.parent_)
     45      move_data(std::move(from));
     46  }
     47
     48
     49  Impl& Impl::operator=(Impl&& rhs)
     50  {
     51    assert(!head_.parent_);
     52    move_data(std::move(rhs));
     53    assert(validate());
     54    return *this;
    4855  }
    4956
     
    5158  void Impl::move_data(Impl&& from)
    5259  {
    53     assert(0 && "implement me");
     60    assert(head_.parent_ == nullptr);
    5461    head_.parent_ = from.head_.parent_;
    5562    head_.left_ = from.head_.left_;
    56     head_.right_ = from.head_.right_;
    57     head_.parent_->parent_ = &head_;
     63    assert(head_.right_ == &head_);
     64    head_.parent_->right_ = &head_;
    5865    node_count_ = from.node_count_;
    5966    from.reset();
     67    assert(validate());
    6068  }
    6169
  • branches/kendall-score/yat/utility/ranking/Impl.h

    r4065 r4069  
    4545      Impl(Impl&& other);
    4646      Impl& operator=(const Impl& rhs) = delete;
     47      Impl& operator=(Impl&& rhs);
    4748      // Head is the only node with no value. Its parent is the root
    4849      // node and the rest of the tree is in the left branch from the
     
    5354      // typically only called with assert, YAT_ASSERT or similar
    5455      bool validate(void) const;
     56      void reset(void);
    5557    private:
    5658      void move_data(Impl&&);
    57       void reset(void);
    5859    };
    5960  } // end of namespace ranking
  • branches/kendall-score/yat/utility/ranking/Iterator.h

    r4065 r4069  
    3434#include <iterator>
    3535
     36#include <iostream> // debug
    3637namespace theplu {
    3738namespace yat {
     
    6465    Iterator<T>::Iterator(const NodeBase* node)
    6566      : node_(node)
    66     {}
     67    {
     68    }
    6769
    6870
Note: See TracChangeset for help on using the changeset viewer.