1 #ifndef SET_OPERATIONS_H 2 #define SET_OPERATIONS_H 28 template <
class H,
class E,
class A>
34 template <
class Op,
class Pred,
class T,
class ... U>
35 decltype(
auto) select_and_invoke(Op&& op, [[maybe_unused]] Pred pred, T&& first)
37 return std::invoke(std::forward<Op>(op), std::forward<T>(first));
41 template <
class Op,
class Pred,
class T,
class U,
class ... Args>
42 decltype(
auto) select_and_invoke(Op&& op, Pred pred, T&& first, U&& second, Args&& ... args)
46 if(pred(static_cast<const T&>(first), static_cast<const U&>(second)))
48 return select_and_invoke(
50 [&op, &first](
auto&& f,
auto&& ... a) {
53 forward<decltype(f)>(f), forward<T>(first), forward<decltype(a)>(a)...
56 pred, forward<U>(second), forward<Args>(args) ...
61 return select_and_invoke(
63 [&op, &second](
auto&& f,
auto&& ... a) {
66 forward<decltype(f)>(f), forward<U>(second), forward<decltype(a)>(a)...
69 pred, forward<T>(first), forward<Args>(args) ...
99 class = std::enable_if_t<
100 detail::is_any_set_v<std::decay_t<T>>
101 and (std::is_same_v<std::decay_t<T>, std::decay_t<U>> and ...)
107 #if !(defined(__GNUC__) && (__GNUC__ == 7)) 112 std::size_t max_total_size = (first.size() + ... + args.size());
113 auto is_better = [](
auto&& left,
auto&& right) {
115 constexpr
bool left_is_rvalue = std::is_rvalue_reference_v<decltype(left)>;
116 constexpr
bool right_is_rvalue = std::is_rvalue_reference_v<decltype(right)>;
117 if constexpr(left_is_rvalue != right_is_rvalue)
118 return right_is_rvalue;
120 return left.bucket_count() < right.bucket_count();
122 auto union_of_impl = [=](
auto&& f,
auto&& ... sets) -> std::decay_t<T> {
124 result.max_load_factor(1.0);
125 result.reserve(max_total_size);
126 (result.update(
std::forward<decltype(sets)>(sets)) , ...);
129 return detail::select_and_invoke(
130 union_of_impl, is_better, std::forward<T>(first), std::forward<U>(args)...
154 class = std::enable_if_t<
155 detail::is_any_set_v<std::decay_t<T>>
156 and (std::is_same_v<std::decay_t<T>, std::decay_t<U>> and ...)
161 auto is_better = [](
auto&& left,
auto&& right) {
163 constexpr
bool left_is_rvalue = std::is_rvalue_reference_v<decltype(left)>;
164 constexpr
bool right_is_rvalue = std::is_rvalue_reference_v<decltype(right)>;
165 if constexpr(left_is_rvalue != right_is_rvalue)
166 return right_is_rvalue;
168 return left.size() > right.size();
170 auto intersection_of_impl = [](
auto&& f,
const auto& ...
set) -> std::decay_t<T> {
172 result.max_load_factor(1.0);
173 auto pos = result.begin();
174 while(pos != result.end())
176 const auto& any_v = *pos;
177 auto has_value = [&](
const auto& s) {
return s.contains_value(any_v); };
178 if(not static_cast<bool>((has_value(
set) and ...)))
180 pos = result.erase(pos);
189 return detail::select_and_invoke(
190 intersection_of_impl, is_better, std::forward<T>(first), std::forward<U>(args)...
215 class = std::enable_if_t<
216 detail::is_any_set_v<std::decay_t<T>>
217 and (std::is_same_v<std::decay_t<T>, std::decay_t<U>> and ...)
222 auto is_better = [](
auto&& left,
auto&& right) {
224 constexpr
bool left_is_rvalue = std::is_rvalue_reference_v<decltype(left)>;
225 constexpr
bool right_is_rvalue = std::is_rvalue_reference_v<decltype(right)>;
226 if constexpr(left_is_rvalue != right_is_rvalue)
227 return right_is_rvalue;
229 return left.bucket_count() < right.bucket_count();
231 auto symmetric_difference_of_impl = [](
auto&& f,
auto&& ...
set) -> std::decay_t<T> {
232 std::decay_t<std::decay_t<T>> result(
std::forward<decltype(f)>(f));
233 result.max_load_factor(1.0);
234 auto inplace_symdiff = [&](
auto&& s) {
235 result ^= std::forward<decltype(s)>(s);
237 (... , inplace_symdiff(
std::forward<decltype(
set)>(
set)));
240 return detail::select_and_invoke(
241 symmetric_difference_of_impl, is_better, std::forward<T>(first), std::forward<U>(args)...
265 class = std::enable_if_t<
266 detail::is_any_set_v<std::decay_t<T>>
267 and (std::is_same_v<std::decay_t<T>, std::decay_t<U>> and ...)
272 if constexpr(std::is_rvalue_reference_v<decltype(left)>)
275 result.max_load_factor(1.0);
277 for(
auto pos = result.begin(); pos != result.end();)
279 if(((right.contains_value(*pos)) or ...))
281 pos = result.erase(pos);
292 std::decay_t<T> result(left.bucket_count());
294 for(
auto pos = left.begin(); pos != left.end(); ++pos)
296 if(not ((right.contains_value(*pos)) or ...))
297 result.push(left.dup(pos));
314 template <
class H,
class E,
class A>
319 for(
const auto& v: sub)
338 template <
class H,
class E,
class A>
354 class = std::enable_if_t<
355 detail::is_any_set_v<std::decay_t<T>>
356 and std::is_same_v<std::decay_t<T>, std::decay_t<U>>
360 {
return union_of(std::forward<T>(left), std::forward<U>(right)); }
363 template <
class H,
class E,
class A>
368 template <
class H,
class E,
class A>
370 {
return left.
update(right); }
376 class = std::enable_if_t<
377 detail::is_any_set_v<std::decay_t<T>>
378 and std::is_same_v<std::decay_t<T>, std::decay_t<U>>
382 {
return std::forward<T>(left) + std::forward<U>(right); }
385 template <
class H,
class E,
class A>
390 template <
class H,
class E,
class A>
392 {
return left += right; }
403 class = std::enable_if_t<
404 detail::is_any_set_v<std::decay_t<T>>
405 and std::is_same_v<std::decay_t<T>, std::decay_t<U>>
409 {
return intersection_of(std::forward<T>(left), std::forward<U>(right)); }
412 template <
class H,
class E,
class A>
417 template <
class H,
class E,
class A>
430 class = std::enable_if_t<
431 detail::is_any_set_v<std::decay_t<T>>
432 and std::is_same_v<std::decay_t<T>, std::decay_t<U>>
436 {
return difference_of(std::forward<T>(left), std::forward<U>(right)); }
439 template <
class H,
class E,
class A>
444 template <
class H,
class E,
class A>
457 class = std::enable_if_t<
458 detail::is_any_set_v<std::decay_t<T>>
459 and std::is_same_v<std::decay_t<T>, std::decay_t<U>>
467 class H,
class E,
class A,
class U,
468 class = std::enable_if_t<std::is_same_v<AnySet<H, E, A>, std::decay_t<U>>>
472 for(
auto pos = right.begin(); pos != right.end();)
475 std::forward<U>(right), pos
490 template <
class H,
class E,
class A>
495 template <
class H,
class E,
class A>
497 {
return is_subset_of(left, right) and (left.size() < right.size()); }
500 template <
class H,
class E,
class A>
505 template <
class H,
class E,
class A>
515 template <
class H,
class E,
class C>
521 auto pos =
set.begin();
523 for(
auto stop =
set.end(); pos != stop; ++pos)
std::decay_t< T > operator|(T &&left, U &&right)
Compute the union of left and right as if by union_of(left, right);
Definition: SetOperations.h:381
AnySet< H, E, A > & operator|=(AnySet< H, E, A > &left, AnySet< H, E, A > &&right)
Compute the union of left and right as if by left = (left + right);
Definition: SetOperations.h:386
AnySet< H, E, A > & operator+=(AnySet< H, E, A > &left, AnySet< H, E, A > &&right)
Compute the union of left and right as if by left = (left + right);
Definition: SetOperations.h:364
bool contains_value(const value_type &any_v) const
Check if this contains the same value as another set.
Definition: AnySet.h:1367
bool is_subset_of(const AnySet< H, E, A > &sub, const AnySet< H, E, A > &super)
Determine whether sub is a subset of super.
Definition: SetOperations.h:315
bool is_superset_of(const AnySet< H, E, A > &super, const AnySet< H, E, A > &sub)
Determine whether super is a superset of sub.
Definition: SetOperations.h:339
size_type size() const noexcept
Gets the number of elements in the set, i.e. std::distance(begin(), end()).
Definition: AnySet.h:877
std::decay_t< T > intersection_of(T &&first, U &&... args)
Get the intersection of a group of AnySet instances.
Definition: SetOperations.h:159
std::decay_t< T > operator-(T &&left, U &&right)
Compute the (asymmetric) difference of left and right as if by difference_of(left, right);
Definition: SetOperations.h:435
std::decay_t< T > difference_of(T &&left, const U &... right)
Get the (asymmetric) difference of a group of AnySet instances.
Definition: SetOperations.h:270
AnySet< H, E, A > & operator^=(AnySet< H, E, A > &left, U &&right)
Compute the symmetric difference of left and right as if by left = (left ^ right); ...
Definition: SetOperations.h:470
std::decay_t< T > operator &(T &&left, U &&right)
Compute the intersection of left and right as if by intersection_of(left, right); ...
Definition: SetOperations.h:408
auto splice_or_copy(T &&other, const_iterator first, const_iterator last) -> std::pair< decltype(other.begin()), decltype(other.begin())>
Copies or moves the elements in the range [first, last) from other into this.
Definition: AnySet.h:1922
Primary classes and utility functions for AnySet.
Definition: SetOperations.h:21
std::decay_t< T > operator^(T &&left, U &&right)
Compute the symmetric difference of left and right as if by symmetric_difference_of(left, right);
Definition: SetOperations.h:462
AnySet< H, E, A > & operator &=(AnySet< H, E, A > &left, AnySet< H, E, A > &&right)
Compute the intersection of left and right as if by left = (left & right);
Definition: SetOperations.h:413
bool operator>(const AnySet< H, E, A > &left, const AnySet< H, E, A > &right)
Semantically equivalent to is_subset_of(left, right) && !(left.size() == right.size());.
Definition: SetOperations.h:506
std::decay_t< T > symmetric_difference_of(T &&first, U &&... args)
Get the symmetric difference of a group of AnySet instances.
Definition: SetOperations.h:220
AnySet< H, E, A > & operator-=(AnySet< H, E, A > &left, AnySet< H, E, A > &&right)
Compute the (asymmetric) difference of left and right as if by left = (left - right); ...
Definition: SetOperations.h:440
std::decay_t< T > union_of(T &&first, U &&... args)
Get the union of a group of AnySet instances.
Definition: SetOperations.h:104
bool operator>=(const AnySet< H, E, A > &left, const AnySet< H, E, A > &right)
Semantically equivalent to is_superset_of(left, right);.
Definition: SetOperations.h:501
AnySet is an associative container that contains a set of unique objects of any constructible type...
Definition: AnySet.h:104
std::pair< node_handle, iterator > pop(const_iterator pos_)
Remove and return the element at the position pointed to by pos from the set.
Definition: AnySet.h:1743
std::decay_t< T > operator+(T &&left, U &&right)
Compute the union of left and right as if by union_of(left, right);
Definition: SetOperations.h:359
Definition: SetOperations.h:26
AnySet & update(const AnySet &other)
Add copies of elements from other.
Definition: AnySet.h:1202