Advertisement
erove

Untitled

Sep 23rd, 2021 (edited)
1,166
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.90 KB | None | 0 0
  1. #pragma once
  2. #include <cstdlib>
  3. #include <type_traits>
  4. #include <iterator>
  5. #include <cassert>
  6.  
  7. namespace intrusive {
  8.   struct default_tag;
  9.  
  10.   struct base_list_element {
  11.     base_list_element();
  12.  
  13.     base_list_element(base_list_element const&);
  14.     base_list_element(base_list_element&&);
  15.     base_list_element& operator=(base_list_element const&);
  16.     base_list_element& operator=(base_list_element&&);
  17.  
  18.     ~base_list_element();
  19.  
  20.     void unlink();
  21.  
  22.     template<typename T_, typename Tag_>
  23.     friend struct list;
  24.  
  25.   private:
  26.     void copy_base_list_element(base_list_element&& other);
  27.     base_list_element* prev;
  28.     base_list_element* next;
  29.   };
  30.  
  31.  
  32.   template <typename Tag = default_tag>
  33.   struct list_element : base_list_element {};
  34.  
  35.  
  36.   template <typename T, typename Tag = default_tag>
  37.   struct list {
  38.  
  39.   private:
  40.     template <typename Type>
  41.     struct base_iterator;
  42.  
  43.   public:
  44.     using node = list_element<Tag>;
  45.     using iterator = base_iterator<T>;
  46.     using const_iterator = base_iterator<T const>;
  47.  
  48.     static_assert(std::is_convertible_v<T&, list_element<Tag>&>,
  49.           "value type is not convertible to list_element");
  50.  
  51.     list() noexcept : fake() {
  52.       make_loop();
  53.     }
  54.  
  55.     list(list const&) = delete;
  56.  
  57.     list(list&& other) noexcept : list() {
  58.       copy_list(std::move(other));
  59.     }
  60.  
  61.     ~list() {
  62.       clear();
  63.     }
  64.  
  65.     list& operator=(list const&) = delete;
  66.  
  67.     list& operator=(list&& other) noexcept {
  68.       clear();
  69.       copy_list(std::move(other));
  70.       return *this;
  71.     }
  72.  
  73.     void clear() noexcept {
  74.       while (!empty()) {
  75.         pop_front();
  76.       }
  77.     }
  78.  
  79.     void push_back(T& value) noexcept {
  80.       insert(end(), value);
  81.     }
  82.  
  83.     void pop_back() noexcept {
  84.       erase(std::prev(end()));
  85.     }
  86.  
  87.     T& back() noexcept {
  88.       return *(std::prev(end()));
  89.     }
  90.  
  91.     T const& back() const noexcept {
  92.       return *(std::prev(end()));
  93.     }
  94.  
  95.     void push_front(T& value) noexcept {
  96.       insert(begin(), value);
  97.     }
  98.  
  99.     void pop_front() noexcept {
  100.       erase(begin());
  101.     }
  102.  
  103.     T& front() noexcept {
  104.       return *begin();
  105.     }
  106.  
  107.     T const& front() const noexcept {
  108.       return *begin();
  109.     }
  110.  
  111.     bool empty() const noexcept {
  112.       return &fake == fake.next;
  113.     }
  114.  
  115.  
  116.     iterator begin() noexcept {
  117.       return iterator(fake.next);
  118.     }
  119.  
  120.     const_iterator begin() const noexcept {
  121.       return const_iterator(const_cast<base_list_element*>(fake.next));
  122.     }
  123.  
  124.     iterator end() noexcept {
  125.       return iterator(&fake);
  126.     }
  127.  
  128.     const_iterator end() const noexcept {
  129.       return const_iterator(const_cast<node*>(&fake));
  130.     }
  131.  
  132.     iterator insert(const_iterator pos, T& value) noexcept {
  133.       node* value_node = &static_cast<node&>(value);
  134.       if (pos.data != value_node) {
  135.         value_node->unlink();
  136.         link(static_cast<node*>(pos.data->prev), value_node);
  137.         link(value_node, pos.data);
  138.       }
  139.       return iterator(value_node);
  140.     }
  141.  
  142.     iterator erase(const_iterator pos) noexcept {
  143.       iterator iter = iterator(pos.data->next);
  144.       pos.data->unlink();
  145.       return iter;
  146.     }
  147.  
  148.     void splice(const_iterator pos, list&, const_iterator first, const_iterator last) noexcept {
  149.       if (first != last) {
  150.         node* other_left = static_cast<node*>(first.data->prev);
  151.         node* other_right = last.data;
  152.         link(static_cast<node*>(pos.data->prev), first.data);
  153.         link(static_cast<node*>(last.data->prev), pos.data);
  154.         link(other_left, other_right);
  155.       }
  156.     }
  157.  
  158.   private:
  159.     void copy_list(list&& other) {
  160.       if (!other.empty()) {
  161.         other.fake.prev->next = &fake;
  162.         other.fake.next->prev = &fake;
  163.         fake.next = other.fake.next;
  164.         fake.prev = other.fake.prev;
  165.         other.make_loop();
  166.       }
  167.     }
  168.  
  169.     void make_loop() {
  170.       fake.next = &fake;
  171.       fake.prev = &fake;
  172.     }
  173.  
  174.     void link(node* first, node* second) {
  175.       first->next = second;
  176.       second->prev = first;
  177.     }
  178.  
  179.     node fake;
  180.  
  181.     template <typename Type>
  182.     struct base_iterator {
  183.       using iterator_category = std::bidirectional_iterator_tag;
  184.       using difference_type = std::ptrdiff_t;
  185.       using value_type = Type;
  186.       using pointer = Type*;
  187.       using reference = Type&;
  188.  
  189.       base_iterator() = default;
  190.  
  191.       template<typename Other, typename = std::enable_if_t<std::is_const_v<Type> && !std::is_const_v<Other>>>
  192.       base_iterator(base_iterator<Other> const &other) : data(other.data) {}
  193.  
  194.       base_iterator& operator++() {
  195.         data = static_cast<node*>(data->next);
  196.         return *this;
  197.       }
  198.  
  199.       base_iterator operator++(int) {
  200.         base_iterator old(*this);
  201.         ++(*this);
  202.         return old;
  203.       }
  204.  
  205.       base_iterator& operator--() {
  206.         data = static_cast<node*>(data->prev);
  207.         return *this;
  208.       }
  209.  
  210.       base_iterator operator--(int) {
  211.         base_iterator old(*this);
  212.         --(*this);
  213.         return old;
  214.       }
  215.  
  216.       reference operator*() const {
  217.         return static_cast<reference>(*data);
  218.       }
  219.  
  220.       pointer operator->() const {
  221.         return static_cast<pointer>(data);
  222.       }
  223.  
  224.       friend bool operator==(base_iterator const &a, base_iterator const &b) {
  225.         return a.data == b.data;
  226.       }
  227.  
  228.       friend bool operator!=(base_iterator const &a, base_iterator const &b) {
  229.         return a.data != b.data;
  230.       }
  231.  
  232.       template<typename T_, typename Tag_>
  233.       friend struct list;
  234.  
  235.     private:
  236.       base_iterator(node* data) : data(data) {}
  237.       base_iterator(base_list_element* data) : data(static_cast<node*>(data)) {}
  238.       node* data;
  239.     };
  240.   };
  241. }
  242.  
  243. ================
  244. #include "intrusive_list.h"
  245.  
  246. namespace intrusive {
  247.   base_list_element::base_list_element() : prev(), next() {}
  248.  
  249.   base_list_element::base_list_element(base_list_element const&) : prev(), next() {}
  250.  
  251.   base_list_element::base_list_element(base_list_element&& other)
  252.       : base_list_element() {
  253.     copy_base_list_element(std::move(other));
  254.   }
  255.  
  256.   base_list_element& base_list_element::operator=(base_list_element const&) {
  257.     prev = nullptr;
  258.     next = nullptr;
  259.     return *this;
  260.   }
  261.  
  262.   base_list_element& base_list_element::operator=(base_list_element&& other) {
  263.     copy_base_list_element(std::move(other));
  264.     return *this;
  265.   }
  266.  
  267.   void base_list_element::copy_base_list_element(base_list_element&& other) {
  268.     prev = other.prev;
  269.     next = other.next;
  270.     if (other.prev != nullptr) {
  271.       other.prev->next = this;
  272.     }
  273.     if (other.next != nullptr) {
  274.       other.next->prev = this;
  275.     }
  276.     other.prev = nullptr;
  277.     other.next = nullptr;
  278.   }
  279.  
  280.   base_list_element::~base_list_element()  {
  281.     unlink();
  282.   }
  283.  
  284.   void base_list_element::unlink()  {
  285.     if (prev != nullptr) {
  286.       prev->next = next;
  287.       next->prev = prev;
  288.       next = nullptr;
  289.       prev = nullptr;
  290.     }
  291.   }
  292. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement