NSUNI/NSLAR Library a250670
Loading...
Searching...
No Matches
static_set.hpp
Go to the documentation of this file.
1
7
8#pragma once
9
10#include <algorithm>
11#include <array>
12
15
16namespace nnl {
17namespace utl {
27template <typename T, std::size_t max_size>
28class StaticSet {
29 static_assert(std::is_arithmetic_v<T>);
30
31 public:
32 using container_type = typename std::array<T, max_size>;
33 using iterator = typename container_type::const_iterator;
34 using const_iterator = typename container_type::const_iterator;
35 using value_type = T;
36
37 StaticSet() noexcept {}
38
39 StaticSet(std::initializer_list<T> list) {
40 for (const auto& val : list) Insert(val);
41 }
42
43 bool Insert(T value) {
44 std::size_t i = 0;
45 for (; i < size_; i++) {
46 if (data_[i] == value) return false;
47
48 if (data_[i] > value) {
49 for (std::size_t j = size_; j > i && size_ + 1 <= max_size; j--) {
50 assert(j != 0);
51 data_[j] = data_[j - 1];
52 }
53 break;
54 }
55 }
56
57 if (size_ + 1 > max_size) {
58 NNL_THROW(RangeError(NNL_SRCTAG("not enough space")));
59 }
60
61 data_[i] = value;
62
63 size_++;
64
65 return true;
66 }
67
68 bool Contains(T value) const noexcept {
69 return std::find(data_.begin(), data_.begin() + size_, value) != data_.begin() + size_;
70 }
71
72 [[nodiscard]] StaticSet<T, max_size> Join(const StaticSet<T, max_size>& other) const {
73 StaticSet<T, max_size> result;
74
75 std::size_t i = 0, j = 0, k = 0;
76
77 // Merge the two sorted ranges
78 while (i < size_ && j < other.size_ && k < max_size) {
79 if (data_[i] == other.data_[j]) {
80 result.data_[k] = data_[i];
81 i++;
82 j++;
83 } else if (data_[i] < other.data_[j]) {
84 result.data_[k] = data_[i];
85 i++;
86 } else {
87 result.data_[k] = other.data_[j];
88 j++;
89 }
90 k++;
91 }
92 // Add remaining elements
93 while (i < size_ && k < max_size) {
94 result.data_[k] = data_[i];
95 i++;
96 k++;
97 }
98
99 while (j < other.size_ && k < max_size) {
100 result.data_[k] = other.data_[j];
101 j++;
102 k++;
103 }
104
105 result.size_ = k;
106
107 if (i != size_ || j != other.size_) {
108 NNL_THROW(RangeError(NNL_SRCTAG("not enough space")));
109 }
110
111 assert(result.size_ >= size_ && result.size_ >= other.size_);
112 return result;
113 }
114
115 [[nodiscard]] StaticSet<T, max_size> Intersect(const StaticSet<T, max_size>& other) const {
116 StaticSet<T, max_size> new_set;
117 auto new_end = std::set_intersection(data_.begin(), data_.begin() + size_, other.data_.begin(),
118 other.data_.begin() + other.size_, new_set.data_.begin());
119
120 new_set.size_ = static_cast<std::size_t>(std::distance(new_set.data_.begin(), new_end));
121
122 return new_set;
123 }
124
125 [[nodiscard]] StaticSet<T, max_size> Difference(const StaticSet<T, max_size>& other) const {
126 StaticSet<T, max_size> new_set;
127 auto new_end = std::set_difference(data_.begin(), data_.begin() + size_, other.data_.begin(),
128 other.data_.begin() + other.size_, new_set.data_.begin());
129
130 new_set.size_ = static_cast<std::size_t>(std::distance(new_set.data_.begin(), new_end));
131
132 return new_set;
133 }
134
135 bool IsSubset(const StaticSet<T, max_size>& other) const {
136 if (other.Size() > Size()) return false;
137
138 return std::includes(data_.begin(), data_.begin() + size_, other.data_.begin(), other.data_.begin() + other.size_);
139 }
140
141 std::size_t Size() const noexcept { return size_; }
142
143 bool IsEmpty() const noexcept { return size_ == 0; }
144
145 void Clear() noexcept { size_ = 0; }
146
147 const T& operator[](std::size_t index) const noexcept {
148 NNL_EXPECTS_DBG(index < this->Size());
149 return data_[index];
150 }
151
152 bool operator==(const StaticSet& rhs) const noexcept {
153 if (rhs.Size() != Size()) return false;
154
155 for (std::size_t i = 0; i < rhs.Size(); i++)
156 if (data_[i] != rhs.data_[i]) return false;
157
158 return true;
159 }
160
161 const_iterator begin() const noexcept { return data_.cbegin(); }
162
163 const_iterator end() const noexcept { return data_.cbegin() + size_; }
164
165 const_iterator cbegin() const noexcept { return data_.cbegin(); }
166
167 const_iterator cend() const noexcept { return data_.cbegin() + size_; }
168
169 const value_type& front() const noexcept {
170 NNL_EXPECTS_DBG(!this->IsEmpty());
171 return *data_.cbegin();
172 }
173
174 const value_type& back() const noexcept {
175 NNL_EXPECTS_DBG(!this->IsEmpty());
176 return *data_.rcbegin();
177 }
178
179 private:
180 std::size_t size_ = 0;
181 container_type data_;
182};
183
184} // namespace utl
185} // namespace nnl
Defines macros for Design-by-Contract verification.
Defines the library-wide exception hierarchy and error handling macros.
#define NNL_EXPECTS_DBG(precondition)
Debug-only precondition check.
Definition contract.hpp:59
Exception thrown for out-of-range errors.
Definition exception.hpp:111
#define NNL_THROW(object)
Throws an exception or terminates the program if exceptions are disabled.
Definition exception.hpp:46
Definition exception.hpp:56