Guest User

Untitled

a guest
Feb 20th, 2018
51
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.17 KB | None | 0 0
  1. /* author: syn
  2. * license: FreeBSD
  3. */
  4.  
  5.  
  6. #pragma once
  7. #include <utility>
  8. #include <iostream>
  9. #include <memory>
  10. #include <vector>
  11. #include <stdexcept>
  12.  
  13. #define debug(var) std::cerr << "\x1b[33;1m" << __PRETTY_FUNCTION__ << ": \x1b[36;1m " #var "\x1b[0m = " << var << std::endl;
  14.  
  15. #ifndef LIST_WARN_ON_EMPTY_ERASE
  16. #define LIST_WARN_ON_EMPTY_ERASE 0
  17. #endif
  18.  
  19. namespace nvs {
  20.  
  21. template <typename T>
  22. struct list_node {
  23. list_node<T> * next;
  24. list_node<T> * prev;
  25. T* value;
  26. };
  27.  
  28. template <typename T>
  29. class list_iterator {
  30. public:
  31. typedef list_iterator<T> self_type;
  32. typedef typename T::value_type value_type;
  33. typedef typename T::reference reference;
  34. typedef typename T::pointer pointer;
  35. typedef std::forward_iterator_tag iterator_category;
  36. typedef typename T::difference_type difference_type;
  37.  
  38. list_iterator () : ptr_(nullptr) {}
  39. list_iterator (const self_type& other) : ptr_ (other.ptr_) {}
  40. list_iterator (list_node <value_type> * ptr) : ptr_(ptr) {}
  41. list_iterator (self_type&& other) = default;// { ptr_->value = std::move (other.ptr->value); }
  42. self_type& operator = (self_type&& other) = default;// { ptr_->value = std::move (other.ptr_->value); }
  43.  
  44. #pragma GCC diagnostic push
  45. #pragma GCC diagnostic ignored "-Wreturn-local-addr"
  46. self_type& operator++ () { ptr_ = ptr_->next; return *this; }
  47. self_type& operator-- () { ptr_ = ptr_->prev; return *this; }
  48. #pragma GCC diagnostic pop
  49.  
  50. self_type operator++ (int prefix) { self_type tmp = *this; ptr_ = ptr_->next; return tmp; }
  51. self_type operator-- (int prefix) { self_type tmp = *this; ptr_ = ptr_->prev; return tmp; }
  52. reference operator* () { return *(ptr_->value); }
  53. pointer operator-> () { return ptr_->value; }
  54. bool operator== (const self_type& rhs) const { return ptr_ == rhs.ptr_; }
  55. bool operator!= (const self_type& rhs) const { return ptr_ != rhs.ptr_; }
  56.  
  57. list_node < value_type > * ptr_;
  58. };
  59.  
  60. /*
  61. * my::list implements this interface
  62. */
  63. /*
  64. template < typename T, typename alloc_ = std::allocator <T> >
  65. class list {
  66. typedef std::allocator_traits <alloc_> alloc_traits;
  67. public:
  68. typedef list <T, alloc_> self_type;
  69. typedef size_t size_type;
  70. typedef typename alloc_traits::value_type value_type;
  71. typedef typename alloc_traits::pointer pointer;
  72. typedef value_type& reference;
  73. typedef const value_type& const_reference;
  74. typedef typename alloc_traits::difference_type difference_type;
  75.  
  76. typedef list_iterator <self_type> iterator;
  77. typedef list_iterator <const self_type> const_iterator;
  78. typedef std::reverse_iterator <iterator> reverse_iterator;
  79. typedef std::reverse_iterator <const_iterator> const_reverse_iterator;
  80.  
  81. list ();
  82. list (const list&);
  83. list (std::initializer_list <T>);
  84. list (std::vector <T, alloc_>);
  85. ~list ();
  86.  
  87. list& operator = (const list&);
  88.  
  89. inline size_type size () const;
  90.  
  91. value_type& operator [] (size_type);
  92. const value_type& operator [] (size_type) const;
  93.  
  94. friend bool operator == (const list<T, alloc_>&, const list<T, alloc_>&);
  95. friend bool operator != (const list<T, alloc_>&, const list<T, alloc_>&);
  96.  
  97. iterator begin ();
  98. const_iterator cbegin () const;
  99. iterator rbegin ();
  100. const_iterator crbegin ();
  101.  
  102. iterator end ();
  103. const_iterator cend () const;
  104. iterator rend ();
  105. const_iterator crend () const;
  106.  
  107. void push_back (const value_type&);
  108. void push_front (const value_type&);
  109.  
  110. template <typename ... Args>
  111. void emplace_back (Args&& ...);
  112. template <typename ... Args>
  113. void emplace_front (Args&& ...);
  114.  
  115. void pop_back ();
  116. void pop_front ();
  117. const value_type& back () const;
  118. const value_type& front () const;
  119.  
  120. private:
  121. list_node <T> * first_ptr;
  122. list_node <T> * last_ptr;
  123. size_type len;
  124. alloc_ alloc;
  125. };
  126. */
  127.  
  128.  
  129. template < typename T, typename alloc_ = std::allocator <T> >
  130. class list {
  131. typedef std::allocator_traits <alloc_> alloc_traits;
  132. public:
  133. typedef list <T, alloc_> self_type;
  134. typedef size_t size_type;
  135. typedef typename alloc_traits::value_type value_type;
  136. typedef typename alloc_traits::pointer pointer;
  137. typedef value_type& reference;
  138. typedef const value_type& const_reference;
  139. typedef typename alloc_traits::difference_type difference_type;
  140.  
  141. typedef list_iterator <self_type> iterator;
  142. typedef list_iterator <const self_type> const_iterator;
  143. typedef std::reverse_iterator <iterator> reverse_iterator;
  144. typedef std::reverse_iterator <const_iterator> const_reverse_iterator;
  145.  
  146. private:
  147. list_node<T> * dummy;
  148. size_type len;
  149. alloc_ alloc;
  150.  
  151. public:
  152.  
  153. list ():
  154. dummy (nullptr),
  155. len (0),
  156. alloc ()
  157. {
  158. dummy = new list_node <T>;
  159. dummy->next = dummy;
  160. dummy->prev = dummy;
  161. }
  162.  
  163.  
  164. list (const list<T, alloc_>& other):
  165. list ()
  166. {
  167. for (auto it = other.cbegin (); it != other.cend (); it++) {
  168. push_back (*it);
  169. }
  170. }
  171.  
  172.  
  173. list (std::initializer_list < T > il):
  174. list ()
  175. {
  176. for (auto it = il.begin (); it != il.end (); it++)
  177. this->push_back (*it);
  178. }
  179.  
  180.  
  181. list (std::vector<T, alloc_> vec):
  182. list ()
  183. {
  184. for (auto it = vec.begin (); it != vec.end (); it++)
  185. this->push_back (*it);
  186. }
  187.  
  188.  
  189. ~list () {
  190. while (len > 0) this->pop_back ();
  191. delete dummy;
  192. }
  193.  
  194.  
  195. self_type& operator = (const list<T, alloc_>& other) {
  196. while (len > 0) this->pop_back ();
  197. len = 0;
  198.  
  199. for (auto it = other.begin (); it != other.end (); it++)
  200. push_back (*it);
  201.  
  202. return *(this);
  203. }
  204.  
  205.  
  206. inline size_type size () const {
  207. return len;
  208. }
  209.  
  210.  
  211. value_type& operator [] (list<T, alloc_>::size_type idx) {
  212. auto it = this->begin ();
  213. for (size_type i = 0; i < idx; i++) it++;
  214. return *it;
  215. }
  216.  
  217.  
  218. const value_type& operator [] (list<T, alloc_>::size_type idx) const {
  219. auto it = this->cbegin ();
  220. for (size_type i = 0; i < idx; i++) it++;
  221. return *it;
  222. }
  223.  
  224.  
  225. friend bool operator == (const list<T, alloc_>& l1, const list<T, alloc_>& l2) {
  226. if (l1.size () != l2.size ()) return false;
  227. auto it1 = l1.begin ();
  228. auto it2 = l2.begin ();
  229. for (; it1 != l1.end () && it2 != l2.end (); it1++, it2++) {
  230. if (*it1 != *it2) return false;
  231. }
  232.  
  233. return true;
  234. }
  235.  
  236.  
  237. friend bool operator != (const list<T, alloc_>& l1, const list<T, alloc_>& l2) {
  238. return !(l1 == l2);
  239. }
  240.  
  241.  
  242. iterator begin () { return iterator (dummy->next); }
  243. const_iterator cbegin () const { return const_iterator (dummy->next); }
  244. iterator end () { return iterator (dummy); }
  245. const_iterator cend () const { return const_iterator (dummy); }
  246.  
  247. reverse_iterator rbegin () { return reverse_iterator (this->end ()); }
  248. const_reverse_iterator crbegin () const { return const_reverse_iterator (this->cend ()); }
  249. reverse_iterator rend () { return reverse_iterator (this->begin ()); }
  250. const_reverse_iterator crend () const { return const_reverse_iterator (this->cbegin ()); }
  251.  
  252.  
  253. void push_back (const list<T, alloc_>::value_type& val) {
  254. this->insert (end (), val);
  255. }
  256.  
  257.  
  258. template <typename ... Args>
  259. iterator insert (iterator pos, Args&& ... args) {
  260. pointer val_copy = alloc.allocate (1);
  261. alloc.construct (val_copy, args ...);
  262.  
  263. auto hooker = new list_node<T>;
  264. hooker->value = val_copy;
  265.  
  266. // hook
  267. hooker->next = pos.ptr_;
  268. hooker->prev = pos.ptr_->prev;
  269. pos.ptr_->prev->next = hooker;
  270. pos.ptr_->prev = hooker;
  271.  
  272. len++;
  273.  
  274. return ++pos;
  275. }
  276.  
  277.  
  278. iterator erase (iterator pos) {
  279. #if LIST_WARN_ON_EMPTY_ERASE
  280. if (len <= 0) throw std::runtime_error ("Trying to erase from epmty list.");
  281. #endif
  282. pos++;
  283. alloc.destroy (pos.ptr_->prev->value);
  284. alloc.deallocate (pos.ptr_->prev->value, 1);
  285. auto before = pos.ptr_->prev->prev;
  286. delete pos.ptr_->prev;
  287. before->next = pos.ptr_;
  288. pos.ptr_->prev = before;
  289. len--;
  290. return pos;
  291. }
  292.  
  293.  
  294. void push_front (const list<T, alloc_>::value_type& val) {
  295. this->insert (begin (), val);
  296. }
  297.  
  298.  
  299. template <typename ... Args>
  300. void emplace_back (Args&& ... args) {
  301. this->insert (end (), args ...);
  302. }
  303.  
  304.  
  305. template <typename ... Args>
  306. void emplace_front (Args&& ... args) {
  307. this->insert (begin (), args ...);
  308. }
  309.  
  310.  
  311. void pop_back () {
  312. auto it = end ();
  313. --it;
  314. this->erase (it);
  315. }
  316.  
  317.  
  318. void pop_front () {
  319. this->erase (begin ());
  320. }
  321.  
  322.  
  323. const value_type& back () const {
  324. return *(crbegin ());
  325. }
  326.  
  327.  
  328. const value_type& front () const {
  329. return *(cbegin ());
  330. }
  331.  
  332. }; // class list
  333.  
  334. } // namespace nvs
Add Comment
Please, Sign In to add comment