1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186 | #pragma once
#include <set><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <unordered_set><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <iterator><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <optional><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <ranges><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <algorithm><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <concepts><--- Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include "internal/dev_env.hpp"
#include "internal/types.hpp"
#include "utility/functional.hpp"
namespace uni {
namespace internal {
template<class Set>
struct set_wrapper : Set {
using Set::Set;
using value_type = typename Set::value_type;
using size_type = internal::size_t;
template<class Key>
auto remove(Key&& key) noexcept(NO_EXCEPT) { return this->extract(std::forward<Key>(key)); }
inline auto ssize() const noexcept(NO_EXCEPT) { return std::ranges::ssize(*this); }
inline auto min_element() const noexcept(NO_EXCEPT) { return this->begin(); }
inline auto max_element() const noexcept(NO_EXCEPT) { return std::ranges::prev(this->end()); }
inline auto min() const noexcept(NO_EXCEPT) { return *this->begin(); }
inline auto max() const noexcept(NO_EXCEPT) { return *std::ranges::prev(this->end()); }
inline auto& pop_min() noexcept(NO_EXCEPT) { this->erase(this->begin()); return *this; }
inline auto& pop_max() noexcept(NO_EXCEPT) { this->erase(std::ranges::prev(this->end())); return *this; }
inline auto kth_smallest_element(const size_type k) const noexcept(NO_EXCEPT) {
return std::ranges::next(this->begin(), k);
}
inline auto kth_largest_element(const size_type k) const noexcept(NO_EXCEPT) {
return std::ranges::prev(this->end(), k + 1);
}
inline auto kth_smallest(const size_type k) const noexcept(NO_EXCEPT) {
return *std::ranges::next(this->begin(), k);
}
inline auto kth_largest(const size_type k) const noexcept(NO_EXCEPT) {
return *std::ranges::prev(this->end(), k + 1);
}
inline auto& pop_kth_smallest(const size_type k) const noexcept(NO_EXCEPT) {
return this->erase(std::ranges::next(this->begin(), k));
return *this;<--- Consecutive return, break, continue, goto or throw statements are unnecessary. [+]Consecutive return, break, continue, goto or throw statements are unnecessary. The second statement can never be executed, and so should be removed.
}
inline auto& pop_kth_largest(const size_type k) const noexcept(NO_EXCEPT) {
return this->erase(std::ranges::prev(this->end(), k + 1));
return *this;<--- Consecutive return, break, continue, goto or throw statements are unnecessary. [+]Consecutive return, break, continue, goto or throw statements are unnecessary. The second statement can never be executed, and so should be removed.
}
auto next_element(const typename Set::key_type& key, const size_type _count = 0) const noexcept(NO_EXCEPT) {
size_type count = std::abs(_count);
auto itr = this->lower_bound(key);
const auto begin = this->begin(), end = this->end();
if(itr == end) return this->end();
if(itr == begin) return this->begin();
while(count--) {
if(_count < 0) if(itr-- == begin) return this->begin();<--- Unsigned less than zero
if(_count > 0) if(++itr == end) return this->end();
}
return itr;
}
auto prev_element(const typename Set::key_type& key, const size_type _count = 0) const noexcept(NO_EXCEPT) {
size_type count = std::abs(_count);
auto itr = this->upper_bound(key);
const auto begin = this->begin(), end = this->end();
if(itr == end) return this->end();
if(itr-- == begin) return this->begin();
while(count--) {
if(_count < 0) if(itr-- == begin) return this->begin();<--- Unsigned less than zero
if(_count > 0) if(++itr == end) return this->end();
}
return itr;
}
std::optional<typename Set::value_type> next(const typename Set::key_type& key, size_type count = 0) const noexcept(NO_EXCEPT) {
if(this->empty()) return {};
auto itr = this->lower_bound(key);
const auto end = this->end();
if(itr == end) return {};
while(count--) if(++itr == end) return {};
return { *itr };
}
std::optional<typename Set::value_type> prev(const typename Set::key_type& key, size_type count = 0) const noexcept(NO_EXCEPT) {
if(this->empty()) return {};
auto itr = this->upper_bound(key);
const auto begin = this->begin();
if(itr-- == begin) return {};
while(count--) if(itr-- == begin) return {};
return { *itr };
}
template<class Rhs>
inline set_wrapper& operator|=(Rhs&& rhs) noexcept(NO_EXCEPT) {
set_wrapper res;
std::ranges::set_union(*this, std::forward<Rhs>(rhs), std::inserter(res, res.end()));
this->swap(res);
return *this;
}
template<class Rhs>
inline set_wrapper& operator&=(Rhs&& rhs) noexcept(NO_EXCEPT) {
set_wrapper res;
std::ranges::set_intersection(*this, std::forward<Rhs>(rhs), std::inserter(res, res.end()));
this->swap(res);
return *this;
}
template<class Rhs>
inline set_wrapper& operator^=(Rhs&& rhs) noexcept(NO_EXCEPT) {
set_wrapper res;
std::ranges::set_symmetric_difference(*this, std::forward<Rhs>(rhs), std::inserter(res, res.end()));
this->swap(res);
return *this;
}
template<class... Args>
inline set_wrapper operator|(set_wrapper<Args...> rhs) noexcept(NO_EXCEPT) {
return rhs |= *this;
}
template<class... Args>
inline set_wrapper operator&(set_wrapper<Args...> rhs) noexcept(NO_EXCEPT) {
return rhs &= *this;
}
template<class... Args>
inline set_wrapper operator^(set_wrapper<Args...> rhs) noexcept(NO_EXCEPT) {
return rhs ^= *this;
}
template<class... Args>
inline auto operator<=>(const set_wrapper<Args...>& rhs) const noexcept(NO_EXCEPT) {
const bool leq = this->size() <= rhs.size() && std::ranges::includes(rhs, *this);
const bool geq = rhs.size() <= this->size() && std::ranges::includes(*this, rhs);
if(leq) {
if(geq) return std::partial_ordering::equivalent;
return std::partial_ordering::less;
}
if(geq) return std::partial_ordering::greater;
return std::partial_ordering::unordered;
}
};
} //namespace internal
template<class... Args> using set = internal::set_wrapper<std::set<Args...>>;
template<class... Args> using unordered_set = internal::set_wrapper<std::unordered_set<Args...>>;
template<class... Args> using multiset = internal::set_wrapper<std::multiset<Args...>>;
template<class... Args> using unordered_multiset = internal::set_wrapper<std::unordered_multiset<Args...>>;
} // namespace uni
|