Guest User

Untitled

a guest
Jul 18th, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 24.89 KB | None | 0 0
  1. #ifndef dlist_hxx_
  2. #define dlist_hxx_
  3.  
  4. //===========================================================================
  5.  
  6. #include <algorithm>  // For std::swap
  7. #include <limits>     // For std::numeric_limits
  8. #include <cstddef>    // For std::size_t and std::ptrdiff_t
  9. #include <iterator>   // For std::iterator
  10. #include <initializer_list>
  11.  
  12. //===========================================================================
  13.  
  14. //
  15. // dlist, dlist_iter, dlist_citer
  16. // forward class declarations
  17. //
  18. template <typename T> class dlist;
  19. template <typename T> class dlist_node;
  20. template <typename T> class dlist_iter;
  21. template <typename T> class dlist_citer;
  22.  
  23. //
  24. // Forward declare some functions...
  25. //
  26. template <typename T>
  27. void swap(dlist_node<T>& a, dlist_node<T>& b);
  28.  
  29. template <typename T>
  30. void swap(dlist_iter<T>& a, dlist_iter<T>& b);
  31.  
  32. template <typename T>
  33. void swap(dlist_citer<T>& a, dlist_citer<T>& b);
  34.  
  35. template <typename T>
  36. void swap(dlist<T>& a, dlist<T>& b);
  37.  
  38. //===========================================================================
  39.  
  40. //
  41. // dlist_node
  42. // struct
  43. //
  44. // Represents a node in a doubly-linked list.
  45. //
  46. template <typename T>
  47. class dlist_node
  48. {
  49. public:
  50.   dlist_node()
  51.   : prev_{nullptr}, next_{nullptr}// Set prev_ and next_ to nullptr here.
  52.   {
  53.   }
  54.  
  55.   dlist_node(dlist_node const& n) = delete;
  56.   dlist_node& operator =(dlist_node& node) = delete;
  57.  
  58.   dlist_node(dlist_node&& n)
  59.   : prev_{n.prev_},next_{n.next_},datum_{std::move(n.datum_)}// Set datum_, prev_, and next_.
  60.   // Remember to move
  61.   {
  62.     // Remember to set n's pointers to nullptr.
  63.     n.prev_= n.next_ = nullptr;
  64.   }
  65.  
  66.   dlist_node& operator =(dlist_node&& n)
  67.   {
  68.     // Similar to move constructor code.
  69.     swap(*this,std::move(n));
  70.     return *this;
  71.   }
  72.  
  73.   ~dlist_node() = default;
  74.  
  75.   dlist_node(T const& d, dlist_node* p=nullptr, dlist_node* n=nullptr)
  76.     : prev_{p},next_{n},datum_{d}// Set datum_, prev_, and next_.
  77.   {
  78.   }
  79.  
  80.   dlist_node(T&& d, dlist_node* p=nullptr, dlist_node* n=nullptr)
  81.     : prev_{p},next_{n},datum_{std:move(d)}// Set datum_, prev_, and next_.
  82.  
  83.     // Remember to move.
  84.   {
  85.   }
  86.  
  87.   T& datum()
  88.   {
  89.     // Return datum_
  90.     return datum_;
  91.   }
  92.  
  93.   T const& datum() const
  94.   {
  95.     // Return datum_
  96.     return datum_;
  97.   }
  98.  
  99.   T&& datum_as_rvalue()
  100.   {
  101.     // Return datum_. Ensure it is an rvalue.
  102.     return std::move(datum_);
  103.   }
  104.  
  105.   dlist_node* prev()
  106.   {
  107.     // Return prev_
  108.     return prev_;
  109.   }
  110.  
  111.   dlist_node const* prev() const
  112.   {
  113.     // Return prev_
  114.     return prev_;
  115.   }
  116.  
  117.   dlist_node* next()
  118.   {
  119.     // Return next_
  120.     return next_;
  121.   }
  122.  
  123.   dlist_node const* next() const
  124.   {
  125.     // Return next_
  126.     return next_;
  127.   }
  128.  
  129.   dlist_node* insert_before(T const& datum, dlist_node*& head)
  130.   {
  131.     // This function has been done for you.
  132.     // Notice that a copy is made as it passes the arguments
  133.     // to other insert_before() function...
  134.     return insert_before(T(datum), head);
  135.   }
  136.  
  137.   dlist_node* insert_before(T&& datum, dlist_node*& head)
  138.   {
  139.     // Dynamically allocate a new dlist_node. Call it node.
  140.     // if prev_ is not null then
  141.     //   prev_'s next_ pointer must be set to node
  142.     // otherwise
  143.     //   head must be set to node
  144.     // And finally prev_ must be set to node.
  145.     // return node;
  146.     auto node = new dlist_node(datum, this->prev_, this);
  147.     if (this->prev_ != nullptr)
  148.        this->prev_->next_ = node;
  149.     else
  150.         head = node;
  151.     this->prev_ = node;
  152.     return node;
  153.   }
  154.  
  155.   dlist_node* insert_after(T const& datum, dlist_node*& tail)
  156.   {
  157.     // This function has been done for you.
  158.     // Notice that a copy is made as it passes the arguments
  159.     // to other insert_after() function...
  160.     return insert_after(T(datum), tail);
  161.   }
  162.  
  163.   dlist_node* insert_after(T&& datum, dlist_node*& tail)
  164.   {
  165.     // Dynamically allocate a new dlist_node. Call it node.
  166.     // if next_ is not null then
  167.     //   next_'s prev_ pointer must be set to node
  168.     // otherwise
  169.     //   tail must be set to node
  170.     // And finally next_ must be set to node.
  171.     // return node;
  172.     auto node = new dlist_node(std::forward<T>(datum), this, this->next_);
  173.     if(this->next_!=nullptr)
  174.         this->next_->prev_ = node;
  175.     else
  176.         tail = node;
  177.     this->next_=node;
  178.     return node;
  179.  
  180.   }
  181.  
  182.   // Remove this node from the list...
  183.   static void remove(
  184.     dlist_node* del, dlist_node*& head, dlist_node*& tail)
  185.   {
  186.     // if del's prev_ node is not null
  187.     //   del's prev_'s next_ pointer must be set to del's next_
  188.     // otherwise
  189.     //   head must be set to del's next_
  190.     if(del->prev_!=nullptr)
  191.         del->prev_->next_ = del->next_;
  192.     else
  193.         head = del->next_;
  194.  
  195.     // if del's next_ node is not null
  196.     //   del's next_'s prev_ pointer must be set to del's prev_
  197.     // otherwise
  198.     //   tail must be set to del's prev_
  199.     if(del->next_!=nullptr)
  200.         del->next_->prev_ = del->prev_;
  201.     else
  202.         tail = del->prev_;
  203.  
  204.     // deallocate del
  205.     delete del;
  206.   }
  207.  
  208.   friend void swap<>(dlist_node<T>& a, dlist_node<T>& b);
  209.  
  210. private:
  211.   T datum_;           // Holds the datum
  212.   dlist_node* prev_;  // Points to the previous node
  213.   dlist_node* next_;  // Points to the next node
  214. };
  215.  
  216. //===========================================================================
  217.  
  218. template <typename T>
  219. inline void swap(dlist_node<T>& a, dlist_node<T>& b)
  220. {
  221.   using std::swap;            // Needed.
  222.  
  223.   // swap a and b's prev_
  224.   // swap a and b's next_
  225.   // swap a and b's datum_
  226.   swap(a.datum_, b.datum_); // placed first just in case it throws an exception!
  227.   swap(a.prev_, b.prev_); // copying pointers will never throw
  228.   swap(a.next_, b.next_); // copying pointers will never throw
  229. }
  230.  
  231. //===========================================================================
  232.  
  233. //
  234. // dlist<T>
  235. // class
  236. //
  237. template <typename T>
  238. class dlist
  239. {
  240.   friend class dlist_iter<T>;       // Needed for head_/tail_ access
  241.   friend class dlist_citer<T>;      // Needed for head_/tail_ access
  242.  
  243. public:
  244.   typedef T value_type;
  245.  
  246.   typedef T& reference;
  247.   typedef T const& const_reference;
  248.  
  249.   typedef T* pointer;
  250.   typedef T const* const_pointer;
  251.  
  252.   typedef dlist_iter<T> iterator;
  253.   typedef dlist_citer<T> const_iterator;
  254.  
  255.   typedef std::reverse_iterator<iterator> reverse_iterator;
  256.   typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  257.  
  258.   typedef std::size_t size_type;
  259.   typedef std::ptrdiff_t difference_type;
  260.  
  261.  
  262.   dlist()
  263.       : head_{nullptr},tail_{nullptr}
  264.     // Set head_ and tail_ to null
  265.   {
  266.   }
  267.  
  268.   dlist(size_type n, T const& value = T())
  269.      : dlist()
  270.     // invoke default constructor
  271.   {
  272.     // call std::fill_n
  273.     //   - use std::back_inserter to append elements
  274.     //   - pass in n and value
  275.     std::fill_n(std::back_inserter(this),n,value);
  276.   }
  277.  
  278.   dlist(std::initializer_list<T> i)
  279.      : dlist()
  280.     // invoke default constructor
  281.   {
  282.     // call std::copy
  283.     //   - use i.begin() and i.end()
  284.     //   - use std::back_inserter to append elements
  285.     std::copy(i.begin(),i.end(),std::back_inserter(this));
  286.   }
  287.  
  288.   template <typename InIter>
  289.   dlist(InIter first, InIter last)
  290.      : dlist()
  291.     // invoke default constructor
  292.   {
  293.     // call std::copy
  294.     //   - use back_inserter to append elements
  295.     std::copy(first,last,std::back_inserter(*this));
  296.   }
  297.  
  298.   dlist(dlist<T> const& l)
  299.      : dlist()
  300.     // invoke default constructor
  301.   {
  302.     // call std::copy
  303.     //   - use back_inserter to append elements
  304.     std::copy(l.begin,l.end(),std::back_inserter(*this));
  305.   }
  306.  
  307.   dlist(dlist<T>&& l) noexcept
  308.   {
  309.     // call swap()
  310.     swap(l);
  311.   }
  312.  
  313.   ~dlist()
  314.   {
  315.     // call clear()
  316.     clear();
  317.   }
  318.  
  319.   dlist<T>& operator =(dlist<T> const& l)
  320.   {
  321.     // make a copy of l
  322.     // call swap() with the copy
  323.     // return
  324.     dlist<T> tmp = l;
  325.     swap(tmp);
  326.     return *this;
  327.   }
  328.  
  329.   dlist<T>& operator =(dlist<T>&& l)
  330.   {
  331.     // call swap() on argument
  332.     // return
  333.     swap(l);
  334.     return *this;
  335.   }
  336.  
  337.   void assign(std::initializer_list<T> i)
  338.   {
  339.     // make a dlist using i
  340.     // swap dlist with *this
  341.     swap(dlist(i));
  342.   }
  343.  
  344.   void assign(size_type n, value_type const& value)
  345.   {
  346.     // make a dlist using arguments
  347.     // swap
  348.     swap(dlist(n,value));
  349.   }
  350.  
  351.   template <typename InIter>
  352.   void assign(InIter first, InIter last)
  353.   {
  354.     // make a dlist using arguments
  355.     // swap
  356.     swap(dlist(first,last));
  357.   }
  358.  
  359.   template <typename... Args>
  360.   iterator emplace(iterator pos, Args&&... args)
  361.   {
  362.     // This function has been provided for you.
  363.     if (empty())
  364.     {
  365.       head_ = tail_ = new dlist_node<T>(
  366.         value_type(std::forward<Args>(args)...)
  367.       );
  368.       pos = dlist_iter<T>(this, tail_);
  369.     }
  370.     else
  371.     {
  372.       if (pos.curpos_ == nullptr)
  373.       {
  374.         auto loc = tail_->insert_after(
  375.           value_type(std::forward<Args>(args)...),
  376.           tail_
  377.         );
  378.         pos = dlist_iter<T>(this, loc);
  379.       }
  380.       else
  381.       {
  382.         auto loc = pos.curpos_->insert_before(
  383.           value_type(std::forward<Args>(args)...),
  384.           head_
  385.         );
  386.         pos = dlist_iter<T>(this, loc);
  387.       }
  388.     }
  389.  
  390.     return pos;
  391.   }
  392.  
  393.   template <typename... Args>
  394.   void emplace_front(Args&&... args)
  395.   {
  396.     // call emplace()
  397.     //   - pass an iterator object that represents the
  398.     //     start of the list
  399.     //   - forward all args...
  400.     emplace(begin(),std::forward<Args>(args)...);
  401.   }
  402.  
  403.   template <typename... Args>
  404.   void emplace_back(Args&&... args)
  405.   {
  406.     // call emplace()
  407.     //   - pass an iterator object that represents the
  408.     //     end of the list
  409.     //   - forward all args...
  410.     emplace(end(),std::forward<Args>(args)...);
  411.   }
  412.  
  413.   iterator begin()
  414.   {
  415.     // return a begin dlist_iter<T>
  416.     return dlist_iter<T>(this,head_);
  417.   }
  418.  
  419.   const_iterator begin() const
  420.   {
  421.     // return a begin dlist_citer<T>
  422.     return dlist_citer<T>(this,head_);
  423.   }
  424.  
  425.   const_iterator cbegin() const
  426.   {
  427.     // return a begin dlist_citer<T>
  428.     return dlist_citer<T>(this,head_);
  429.   }
  430.  
  431.   reverse_iterator rbegin()
  432.   {
  433.     // return correct reverse_iterator
  434.     return dlist_iter<T>(std::reverse(head_));
  435.   }
  436.  
  437.   const_reverse_iterator rbegin() const
  438.   {
  439.     // return correct reverse_iterator
  440.     return dlist_citer<T>(std::reverse(head_));
  441.   }
  442.  
  443.   const_reverse_iterator crbegin() const
  444.   {
  445.     // return correct reverse_iterator
  446.     return dlist_citer<T>(std::reverse(head_));
  447.   }
  448.  
  449.   iterator end()
  450.   {
  451.     // return an end dlist_iter<T>
  452.     return dlist_iter<T>(tail_);
  453.   }
  454.  
  455.   const_iterator end() const
  456.   {
  457.     // return an end dlist_citer<T>
  458.     return dlist_citer<T>(tail_);
  459.  
  460.   }
  461.  
  462.   const_iterator cend() const
  463.   {
  464.     // return an end dlist_citer<T>
  465.     return dlist_citer<T>(tail_);
  466.   }
  467.  
  468.   reverse_iterator rend()
  469.   {
  470.     // return the correct reverse_iterator
  471.     return dlist_iter<T>(std::reverse(tail_));
  472.   }
  473.  
  474.   const_reverse_iterator rend() const
  475.   {
  476.     // return the correct reverse_iterator
  477.     return dlist_citer<T>(std::reverse(tail_));
  478.   }
  479.  
  480.   const_reverse_iterator crend() const
  481.   {
  482.     // return the correct reverse_iterator
  483.     return dlist_citer<T>(std::reverse(tail_));
  484.   }
  485.  
  486.   bool empty() const
  487.   {
  488.     // This has been provided for you...
  489.     return head_ == nullptr;
  490.   }
  491.  
  492.   size_type size() const
  493.   {
  494.     // Write code to compute the size.
  495.     dlist_iter<T> tmp = head_;
  496.     int i = 0;
  497.     while(tmp!=nullptr){
  498.       tmp++;
  499.       i++;
  500.     }
  501.     return i;
  502.   }
  503.  
  504.   size_type max_size() const
  505.   {
  506.     // This has been provided for you...
  507.     return std::numeric_limits<size_type>::max();
  508.   }
  509.  
  510.   reference front()
  511.   {
  512.     // return the first element
  513.     return &head_;
  514.   }
  515.  
  516.   const_reference front() const
  517.   {
  518.     // return the first element
  519.     return head_;
  520.   }
  521.  
  522.   reference back()
  523.   {
  524.     // return the last element
  525.     return tail_;
  526.   }
  527.  
  528.   const_reference back() const
  529.   {
  530.     // return the last element
  531.     return tail_;
  532.   }
  533.  
  534.   void push_front(value_type const& i)
  535.   {
  536.     // if empty() then
  537.     //   head_ = tail_ = new node
  538.     // otherwise
  539.     //   insert_before the first node in the list
  540.    
  541.    if(empty())
  542.      head_= tail_= new dlist_node<T>(value_type(i));
  543.     else
  544.       head_->insert_before(T(i),head_);
  545.    
  546.  
  547.  
  548.   }
  549.  
  550.   void push_front(value_type&& i)
  551.   {
  552.     // Same as lvalue push_front() except
  553.     //   - remember to std::forward all value_type arguments
  554.      if(empty())
  555.        head_=tail_= new dlist_node<T>(value_type(std::forward<value_type>(i)));
  556.     else
  557.      head_->insert_before(T(std::forward<value_type>(i)),head_);
  558.    
  559.   }
  560.  
  561.   void pop_front()
  562.   {
  563.     // call dlist_node<T>::remove() appropriately
  564.     head_->remove(head_,head_,tail_);
  565.   }
  566.  
  567.   void push_back(value_type const& i)
  568.   {
  569.     // if empty() then
  570.     //   head_ = tail_ = new node
  571.     // otherwise
  572.     //   insert_after the last node in the list
  573.     if(empty())
  574.       head_=tail_=new dlist_node<T>(value_type(i));
  575.     else
  576.       tail_->insert_after(T(i),tail_);
  577.   }
  578.  
  579.   void push_back(value_type&& i)
  580.   {
  581.     // Same as lvalue push_back() except
  582.     //   - remember to std::forward all value_type arguments
  583.     if(empty())
  584.       head_= tail_=new dlist_node<T>(T(std::forward<value_type>(i)));
  585.     else
  586.       tail_->insert_after(T(std::forward<value_type>(i)),tail_);
  587.   }
  588.  
  589.   void pop_back()
  590.   {
  591.     // call dlist_node<T>::remove() appropriately
  592.     tail_->remove(tail_,head_,tail_);
  593.   }
  594.  
  595.   iterator insert(iterator pos, value_type const& value)
  596.   {
  597.     // identical to emplace() except there are no moves or forwards
  598.     if (empty()){
  599.       head_=tail_=new dlist_node<T>(value);
  600.       pos = dlist_iter<T>(this,tail_);
  601.     }
  602.     else{
  603.       if(pos.curpos_ == nullptr){
  604.     auto loc = tail_->insert_after(value,tail_);
  605.     pos = dlist_iter<T>(this,loc);
  606.       }
  607.       else{
  608.     auto loc = pos.curpos_->insert_before(value,head_);
  609.     pos = dlist_iter<T>(this,loc);
  610.       }
  611.     }
  612.     return pos;
  613.   }
  614.  
  615.   template <typename InIter>
  616.   void insert(iterator pos, InIter first, InIter last)
  617.   {
  618.     // loop through [first,last) calling insert(pos,value)
  619.     while(first!=last){
  620.       insert(pos,pos->value);
  621.       first = first->next_;
  622.     }
  623.   }
  624.  
  625.   iterator erase(iterator pos)
  626.   {
  627.     // make a copy of pos
  628.     // ++ the copy
  629.     //   - NOTE: This is needed because when the node is destroyed the
  630.     //     iterator is invalid. Thus, one needs to move to the next node
  631.     //     BEFORE the current one is destroyed. Otherwise, the proper
  632.     //     return value cannot be computed.
  633.     // remove the node
  634.     // return the copy
  635.     dlist_iter<T> tmp = pos;
  636.     ++tmp;
  637.     remove(pos);
  638.     return tmp;
  639.   }
  640.  
  641.   iterator erase(iterator pos, iterator last)
  642.   {
  643.     // loop through [pos,last) calling erase()
  644.     // return pos
  645.     while(pos!=last){
  646.       dlist_iter<T> tmp = pos;
  647.       ++pos;
  648.       erase(tmp);
  649.     }
  650.     return pos;
  651.   }
  652.  
  653.   void swap(dlist& l) noexcept
  654.   {
  655.     using std::swap;        // Needed
  656.  
  657.     // swap the head_s
  658.     // swap the tail_s
  659.     swap(head_,l.head_);
  660.     swap(tail_,l.tail_);
  661.  
  662.   }
  663.  
  664.   void clear()
  665.   {
  666.     // loop while the list is not empty
  667.     //   remove the first node
  668.     dlist_node<T>* tmp = head_;
  669.     while(size() !=0){
  670.      
  671.       head_=head_->next();
  672.       head_->remove(tmp,head_,tail_);
  673.       tmp = head_;
  674.     }
  675.  
  676.     // NOTE: There are multiple ways to do this. The above method is a
  677.     //       straight-forward one.
  678.   }
  679.  
  680. private:
  681.   dlist_node<T>* head_;
  682.   dlist_node<T>* tail_;
  683. };
  684.  
  685. //===========================================================================
  686.  
  687. template <typename T>
  688. bool operator ==(dlist<T> const& a, dlist<T> const& b)
  689. {
  690.   using std::begin;
  691.   using std::end;
  692.   dlist_iter<T> abegin = a.begin();
  693.   dlist_iter<T> aend = a.end();
  694.   dlist_iter<T> bbegin = b.begin();
  695.   dlist_iter<T> bend = b.end();
  696.  
  697.   if(a.size()!=b.size())
  698.     return false;
  699.  
  700.   // write a for loop to simultaneously iterator through a and b
  701.   // to determine if they are the same
  702.   while(abegin!= b.end() && bbegin!=bend){
  703.     if(abegin != bbegin){
  704.       return false;
  705.       break;
  706.     }
  707.     else{
  708.       abegin = abegin->next_;
  709.       bbegin = bbegin->next_;
  710.     }
  711.   }
  712.   return true;
  713.  
  714.   // abort the loop once different elements are found, or,
  715.   // if the end of either list is arrived at
  716.  
  717.   // remember to ensure the return value returns false if the
  718.   // lists are not identical in size
  719.  
  720.   // you are only allowed to iterators and a bool variable in this
  721.   // function
  722. }
  723.  
  724. template <typename T>
  725. inline bool operator !=(dlist<T> const& a, dlist<T> const& b)
  726. {
  727.   // Provided for you...
  728.   return !operator ==(a,b);
  729. }
  730.  
  731. template <typename T>
  732. inline bool operator <(dlist<T> const& a, dlist<T> const& b)
  733. {
  734.   // Provided for you...
  735.   return std::lexicographical_compare(
  736.     a.begin(), a.end(),
  737.     b.begin(), b.end()
  738.   );
  739. }
  740.  
  741. template <typename T>
  742. inline bool operator <=(dlist<T> const& a, dlist<T> const& b)
  743. {
  744.   // a <= b is the same as !(b < a)
  745.   // Write the code in terms of <.
  746.   if (!(b < a))
  747.     return true;
  748.   else
  749.     return false;
  750. }
  751.  
  752. template <typename T>
  753. inline bool operator >(dlist<T> const& a, dlist<T> const& b)
  754. {
  755.   // a > b is the same as b < a
  756.   // Write the code in terms of <.
  757.   if(b<a)
  758.     return true;
  759.   else
  760.     return false;
  761. }
  762.  
  763. template <typename T>
  764. inline bool operator >=(dlist<T> const& a, dlist<T> const& b)
  765. {
  766.   // a >= b is the same as !(a < b)
  767.   // Write the code in terms of <.
  768.   if(!(a<b))
  769.     return true;
  770.   else
  771.     return false;
  772. }
  773.  
  774. template <typename T>
  775. inline void swap(dlist<T>& a, dlist<T>& b)
  776. {
  777.   // This function is trival: it simply calls dlist's swap().
  778.   swap(a,b);
  779. }
  780.  
  781. template <typename T>
  782. inline auto begin(dlist<T>& a) -> decltype(a.begin())
  783. {
  784.   // Provided for you...
  785.   return a.begin();
  786. }
  787.  
  788. template <typename T>
  789. inline auto begin(dlist<T> const& a) -> decltype(a.begin())
  790. {
  791.   // Provided for you...
  792.   return a.begin();
  793. }
  794.  
  795. template <typename T>
  796. inline auto cbegin(dlist<T> const& a) -> decltype(a.cbegin())
  797. {
  798.   // Provided for you...
  799.   return a.cbegin();
  800. }
  801.  
  802. template <typename T>
  803. inline auto rbegin(dlist<T>& a) -> decltype(a.rbegin())
  804. {
  805.   // Provided for you...
  806.   return a.rbegin();
  807. }
  808.  
  809. template <typename T>
  810. inline auto rbegin(dlist<T> const& a) -> decltype(a.rbegin())
  811. {
  812.   // Provided for you...
  813.   return a.rbegin();
  814. }
  815.  
  816. template <typename T>
  817. inline auto crbegin(dlist<T> const& a) -> decltype(a.crbegin())
  818. {
  819.   // Provided for you...
  820.   return a.crbegin();
  821. }
  822.  
  823. template <typename T>
  824. inline auto end(dlist<T>& a) -> decltype(a.end())
  825. {
  826.   // Provided for you...
  827.   return a.end();
  828. }
  829.  
  830. template <typename T>
  831. inline auto end(dlist<T> const& a) -> decltype(a.end())
  832. {
  833.   // Provided for you...
  834.   return a.end();
  835. }
  836.  
  837. template <typename T>
  838. inline auto cend(dlist<T> const& a) -> decltype(a.cend())
  839. {
  840.   // Provided for you...
  841.   return a.cend();
  842. }
  843.  
  844. template <typename T>
  845. inline auto rend(dlist<T>& a) -> decltype(a.rend())
  846. {
  847.   // Provided for you...
  848.   return a.rend();
  849. }
  850.  
  851. template <typename T>
  852. inline auto rend(dlist<T> const& a) -> decltype(a.rend())
  853. {
  854.   // Provided for you...
  855.   return a.rend();
  856. }
  857.  
  858. template <typename T>
  859. inline auto crend(dlist<T> const& a) -> decltype(a.crend())
  860. {
  861.   // Provided for you...
  862.   return a.crend();
  863. }
  864.  
  865. //===========================================================================
  866.  
  867. //
  868. // dlist_iter
  869. // class
  870. //
  871. // This class represents an iterator that operates on dlist.
  872. //
  873. template <typename T>
  874. class dlist_iter :
  875.   public std::iterator<
  876.     std::bidirectional_iterator_tag, T
  877.   >
  878. {
  879.   friend class dlist<T>;          // Permit access to private constructor
  880.   friend class dlist_citer<T>;    // Permit access to member variables
  881.  
  882.   explicit dlist_iter(dlist<T>* l, dlist_node<T>* n)
  883.     : list_(l), curpos_(n)// Set list_ and curpos_
  884.   {
  885.   }
  886.  
  887. public:
  888.   dlist_iter(dlist_iter const& iter) = default;
  889.   dlist_iter& operator =(dlist_iter const& iter) = default;
  890.  
  891.   bool operator ==(dlist_iter const& iter) const
  892.   {
  893.     // member variable equality test
  894.     //check this
  895.     return(curpos_ == iter.curpos_);
  896.   }
  897.  
  898.   bool operator !=(dlist_iter const& iter) const
  899.   {
  900.     // member variable inequality test
  901.     //check this
  902.     return (curpos_!=iter.curpos_);
  903.   }
  904.  
  905.   T& operator *() const
  906.   {
  907.     // Provided for you...
  908.     return curpos_->datum();
  909.   }
  910.  
  911.   T* operator ->() const
  912.   {
  913.     // return a pointer --not a reference!
  914.     return &curpos_->datum_;
  915.   }
  916.  
  917.   dlist_iter& operator ++()
  918.   {
  919.     // set curpos_ to the next pointer value
  920.     // return this object
  921.     curpos_ = curpos_->next();
  922.     return *this;
  923.  
  924.   }
  925.  
  926.   dlist_iter operator ++(int)
  927.   {
  928.     // make a copy of the iterator
  929.     // call the prefix ++ operator
  930.     // return the copy
  931.     dlist_iter tmp = *this;
  932.     operator ++();
  933.     return tmp;
  934.   }
  935.  
  936.   dlist_iter& operator --()
  937.   {
  938.     // NOTE: Take care with this code. It is not as simple as
  939.     //       the ++ operator since the end is one past the real
  940.     //       end and so curpos_ can be null!
  941.  
  942.     // if curpos_ is not null, then
  943.     //   set curpos_ to the prev position
  944.     // otherwise
  945.     //   set curpos_ to pointer to the last node in the list
  946.     if(curpos_!=nullptr)
  947.         curpos_=curpos_->prev_;
  948.     else
  949.         curpos_ = list_->tail_;
  950.         return *this;
  951.  
  952.     // return this object
  953.   }
  954.  
  955.   dlist_iter operator --(int)
  956.   {
  957.     // Very similar to the ++ postfix operator
  958.     dlist_iter tmp = *this;
  959.     operator --();
  960.     return tmp;
  961.   }
  962.  
  963.   friend void swap<>(dlist_iter<T>& a, dlist_iter<T>& b);
  964.  
  965. private:
  966.   dlist<T>* list_;
  967.   dlist_node<T>* curpos_;
  968. };
  969.  
  970. //===========================================================================
  971.  
  972. template <typename T>
  973. inline void swap(dlist_iter<T>& a, dlist_iter<T>& b)
  974. {
  975.   using std::swap;              // Needed
  976.  
  977.   // swap a and b's list_ and curpos_ variables
  978.   swap(a.list_,b.list_);
  979.   swap(a.curpos_,b.curpos_);
  980. }
  981.  
  982. //===========================================================================
  983.  
  984. //
  985. // dlist_citer
  986. // class
  987. //
  988. // This class represents an constant iterator that operates on dlist.
  989. //
  990. template <typename T>
  991. class dlist_citer :
  992.   public std::iterator<
  993.     std::bidirectional_iterator_tag,
  994.     T const, std::ptrdiff_t, T const*, T const&
  995.   >
  996. {
  997.   friend class dlist<T>;      // Permit access to private constructor
  998.  
  999.   explicit dlist_citer(dlist<T> const* l, dlist_node<T> const* n)
  1000.     : list_(l),curpos_(n)// Set list_ and curpos_
  1001.   {
  1002.   }
  1003.  
  1004. public:
  1005.   //check this
  1006.   dlist_citer(dlist_iter<T> const& iter)
  1007.     : list_(iter->list_),curpos_(iter->curpos_)// Set list_ and curpos_
  1008.   {
  1009.   }
  1010.  
  1011.   dlist_citer(dlist_citer const& iter) = default;
  1012.  
  1013.   dlist_citer& operator =(dlist_iter<T> const& iter)
  1014.   {
  1015.     // Set list_ and curpos_
  1016.     // return *this;
  1017.     list_=iter->list_;
  1018.     curpos_=iter->curpos_;
  1019.     return *this;
  1020.  
  1021.   }
  1022.  
  1023.   dlist_citer& operator =(dlist_citer const& iter) = default;
  1024.  
  1025.   bool operator ==(dlist_citer const& iter) const
  1026.   {
  1027.     // Return true if the iterators are the same
  1028.     //check this
  1029.     return (*this == iter);
  1030.   }
  1031.  
  1032.   bool operator !=(dlist_citer const& iter) const
  1033.   {
  1034.     // Return true if the iterators are not the same
  1035.     //check this
  1036.     return(*this != iter);
  1037.   }
  1038.  
  1039.   bool operator ==(dlist_iter<T> const& iter) const
  1040.   {
  1041.     // Return true if the iterators are the same
  1042.     //check this
  1043.     return (*this == iter);
  1044.   }
  1045.  
  1046.   bool operator !=(dlist_iter<T> const& iter) const
  1047.   {
  1048.     // Return true if the iterators are not the same
  1049.     //check this
  1050.     return (*this != iter);
  1051.   }
  1052.  
  1053.   T const& operator *() const
  1054.   {
  1055.     // Return the datum...
  1056.     // check this
  1057.     return curpos_->datum();
  1058.   }
  1059.  
  1060.   T const* operator ->() const
  1061.   {
  1062.     // Return the datum (as a pointer)
  1063.     return &curpos_->datum_;
  1064.   }
  1065.  
  1066.   dlist_citer& operator ++()
  1067.   {
  1068.     // Similar to dlist_iter's prefix ++
  1069.     curpos_ = curpos_->next_;
  1070.     return *this;
  1071.  
  1072.   }
  1073.  
  1074.   dlist_citer operator ++(int)
  1075.   {
  1076.     // Similar to dlist_iter's postfix ++
  1077.     dlist_citer tmp = curpos_;
  1078.     operator ++();
  1079.     return tmp;
  1080.   }
  1081.  
  1082.   dlist_citer& operator --()
  1083.   {
  1084.     // Similar to dlist_iter's prefix --
  1085.     if(*this != nullptr)
  1086.              curpos_ = curpos_->prev_;
  1087.     else
  1088.              curpos_ = list_->tail_;
  1089.     return *this;
  1090.   }
  1091.  
  1092.   dlist_citer operator --(int)
  1093.   {
  1094.     // Similar to dlist_iter's postfix --
  1095.     dlist_citer tmp = curpos_;
  1096.     operator --();
  1097.     return tmp;
  1098.   }
  1099.  
  1100.   friend void swap<>(dlist_citer<T>& a, dlist_citer<T>& b);
  1101.  
  1102. private:
  1103.   dlist<T> const* list_;
  1104.   dlist_node<T> const* curpos_;
  1105. };
  1106.  
  1107. //===========================================================================
  1108.  
  1109. template <typename T>
  1110. void swap(dlist_citer<T>& a, dlist_citer<T>& b)
  1111. {
  1112.   using std::swap;
  1113.  
  1114.   // swap a and b's list_ and curpos_
  1115.   swap(a.list_,b.list_);
  1116.   swap(a.curpos_,b.curpos_);
  1117. }
  1118.  
  1119. //===========================================================================
  1120.  
  1121. #endif // #ifndef dlist_hxx_
Add Comment
Please, Sign In to add comment