TermOx
unique_queue.hpp
1 #ifndef TERMOX_COMMON_UNIQUE_QUEUE_HPP
2 #define TERMOX_COMMON_UNIQUE_QUEUE_HPP
3 #include <algorithm>
4 #include <cassert>
5 #include <iterator>
6 #include <utility>
7 #include <vector>
8 
9 #include <termox/common/transform_iterator.hpp>
10 
11 namespace ox {
12 
14 
18 template <typename T>
19 class Unique_queue {
20  private:
21  struct Ordered_element {
22  int position;
23  T element;
24  };
25 
27  class Get_element {
28  public:
29  [[nodiscard]] auto operator()(Ordered_element const& e) const
30  -> T const&
31  {
32  return e.element;
33  }
34 
35  [[nodiscard]] auto operator()(Ordered_element& e) const -> T&
36  {
37  return e.element;
38  }
39  };
40 
41  using Internal_container_t = std::vector<Ordered_element>;
42 
43  public:
44  using iterator = Transform_iterator<typename Internal_container_t::iterator,
45  Get_element>;
46 
47  using const_iterator =
48  Transform_iterator<typename Internal_container_t::const_iterator,
49  Get_element>;
50 
51  public:
53  void append(T const& element)
54  {
55  assert(!compressed_but_not_cleared_);
56  data_.push_back({count_, element});
57  ++count_;
58  }
59 
61  void append(T&& element)
62  {
63  assert(!compressed_but_not_cleared_);
64  data_.push_back({count_, std::move(element)});
65  ++count_;
66  }
67 
68  [[nodiscard]] auto size() const -> std::size_t { return data_.size(); }
69 
71 
74  void compress()
75  {
76  std::stable_sort(
77  std::begin(data_), std::end(data_),
78  [](Ordered_element const& a, Ordered_element const& b) {
79  return a.element < b.element;
80  });
81  auto rend =
82  std::unique(std::rbegin(data_), std::rend(data_),
83  [](Ordered_element const& a, Ordered_element const& b) {
84  return a.element == b.element;
85  });
86  data_.erase(std::begin(data_), rend.base());
87  std::sort(std::begin(data_), std::end(data_),
88  [](Ordered_element const& a, Ordered_element const& b) {
89  return a.position < b.position;
90  });
91 #ifndef NDEBUG
92  compressed_but_not_cleared_ = true;
93 #endif
94  }
95 
97  void clear()
98  {
99  data_.clear();
100  count_ = 0;
101 #ifndef NDEBUG
102  compressed_but_not_cleared_ = false;
103 #endif
104  }
105 
106  [[nodiscard]] auto begin() -> iterator
107  {
108  return iterator{std::begin(data_), get_element_};
109  }
110 
111  [[nodiscard]] auto begin() const -> const_iterator
112  {
113  return const_iterator{std::cbegin(data_), get_element_};
114  }
115 
116  [[nodiscard]] auto end() -> iterator
117  {
118  return iterator{std::end(data_), get_element_};
119  }
120 
121  [[nodiscard]] auto end() const -> const_iterator
122  {
123  return const_iterator{std::cend(data_), get_element_};
124  }
125 
126  private:
127  Internal_container_t data_;
128  Get_element get_element_;
129  int count_ = 0;
130 #ifndef NDEBUG
131  bool compressed_but_not_cleared_ = false;
132 #endif
133 };
134 } // namespace ox
135 #endif // TERMOX_COMMON_UNIQUE_QUEUE_HPP
operator*() will apply map to the result of the underlying deref result.
Definition: transform_iterator.hpp:15
A Queue like container holding only unique values.
Definition: unique_queue.hpp:19
void append(T const &element)
Add element to the end of the queue.
Definition: unique_queue.hpp:53
void compress()
Remove duplicate elements, this should be called before using iterators.
Definition: unique_queue.hpp:74
void append(T &&element)
Add element to the end of the queue.
Definition: unique_queue.hpp:61
void clear()
Remove all elements from the queue.
Definition: unique_queue.hpp:97