static_list.hpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Copyright (c) 2018-2025 Jean-Louis Leroy
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // See accompanying file LICENSE_1_0.txt
  4. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. #ifndef BOOST_OPENMETHOD_DETAIL_STATIC_LIST_HPP
  6. #define BOOST_OPENMETHOD_DETAIL_STATIC_LIST_HPP
  7. #include <algorithm>
  8. #include <boost/assert.hpp>
  9. namespace boost::openmethod {
  10. namespace detail {
  11. template<typename T>
  12. class static_list {
  13. public:
  14. static_list(static_list&) = delete;
  15. static_list() = default;
  16. class static_link {
  17. public:
  18. static_link(const static_link&) = delete;
  19. static_link() = default;
  20. auto next() -> T* {
  21. return next_ptr;
  22. }
  23. protected:
  24. friend class static_list;
  25. T* prev_ptr;
  26. T* next_ptr;
  27. };
  28. void push_back(T& node) {
  29. BOOST_ASSERT(node.prev_ptr == nullptr);
  30. BOOST_ASSERT(node.next_ptr == nullptr);
  31. if (!first) {
  32. first = &node;
  33. node.prev_ptr = &node;
  34. return;
  35. }
  36. auto last = first->prev_ptr;
  37. last->next_ptr = &node;
  38. node.prev_ptr = last;
  39. first->prev_ptr = &node;
  40. }
  41. void remove(T& node) {
  42. BOOST_ASSERT(first != nullptr);
  43. auto prev = node.prev_ptr;
  44. auto next = node.next_ptr;
  45. auto last = first->prev_ptr;
  46. node.prev_ptr = nullptr;
  47. node.next_ptr = nullptr;
  48. if (&node == last) {
  49. if (&node == first) {
  50. first = nullptr;
  51. return;
  52. }
  53. first->prev_ptr = prev;
  54. prev->next_ptr = nullptr;
  55. return;
  56. }
  57. if (&node == first) {
  58. first = next;
  59. first->prev_ptr = last;
  60. return;
  61. }
  62. prev->next_ptr = next;
  63. next->prev_ptr = prev;
  64. }
  65. void clear() {
  66. auto next = first;
  67. first = nullptr;
  68. while (next) {
  69. auto cur = next;
  70. next = cur->next_ptr;
  71. cur->prev_ptr = nullptr;
  72. cur->next_ptr = nullptr;
  73. }
  74. }
  75. class iterator {
  76. public:
  77. using iterator_category = std::forward_iterator_tag;
  78. using difference_type = std::ptrdiff_t;
  79. using value_type = T;
  80. using pointer = value_type*;
  81. using reference = value_type&;
  82. iterator() : ptr(nullptr) {
  83. }
  84. explicit iterator(T* p) : ptr(p) {
  85. }
  86. auto operator*() -> reference {
  87. return *ptr;
  88. }
  89. auto operator->() -> pointer {
  90. return ptr;
  91. }
  92. auto operator++() -> iterator& {
  93. BOOST_ASSERT(ptr);
  94. ptr = ptr->next_ptr;
  95. return *this;
  96. }
  97. auto operator++(int) -> iterator {
  98. auto tmp = *this;
  99. ++(*this);
  100. return tmp;
  101. }
  102. friend auto operator==(const iterator& a, const iterator& b) -> bool {
  103. return a.ptr == b.ptr;
  104. };
  105. friend auto operator!=(const iterator& a, const iterator& b) -> bool {
  106. return a.ptr != b.ptr;
  107. };
  108. private:
  109. T* ptr;
  110. };
  111. auto begin() -> iterator {
  112. return iterator(first);
  113. }
  114. auto end() -> iterator {
  115. return iterator(nullptr);
  116. }
  117. class const_iterator {
  118. public:
  119. using iterator_category = std::forward_iterator_tag;
  120. using difference_type = std::ptrdiff_t;
  121. using value_type = const T;
  122. using pointer = value_type*;
  123. using reference = value_type&;
  124. const_iterator() : ptr(nullptr) {
  125. }
  126. explicit const_iterator(T* p) : ptr(p) {
  127. }
  128. auto operator*() -> reference {
  129. return *ptr;
  130. }
  131. auto operator->() -> pointer {
  132. return ptr;
  133. }
  134. auto operator++() -> const_iterator& {
  135. BOOST_ASSERT(ptr);
  136. ptr = ptr->next_ptr;
  137. return *this;
  138. }
  139. auto operator++(int) -> const_iterator {
  140. auto tmp = *this;
  141. ++(*this);
  142. return tmp;
  143. }
  144. friend auto
  145. operator==(const const_iterator& a, const const_iterator& b) -> bool {
  146. return a.ptr == b.ptr;
  147. };
  148. friend auto
  149. operator!=(const const_iterator& a, const const_iterator& b) -> bool {
  150. return a.ptr != b.ptr;
  151. };
  152. private:
  153. T* ptr;
  154. };
  155. auto begin() const -> const_iterator {
  156. return const_iterator(first);
  157. }
  158. auto end() const -> const_iterator {
  159. return const_iterator(nullptr);
  160. }
  161. auto size() const -> std::size_t {
  162. return std::distance(begin(), end());
  163. }
  164. auto empty() const -> bool {
  165. return !first;
  166. }
  167. protected:
  168. T* first;
  169. };
  170. } // namespace detail
  171. } // namespace boost::openmethod
  172. #endif