File indexing completed on 2026-05-10 08:43:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_ADT_SETOPERATIONS_H
0016 #define LLVM_ADT_SETOPERATIONS_H
0017
0018 #include "llvm/ADT/STLExtras.h"
0019
0020 namespace llvm {
0021
0022 namespace detail {
0023 template <typename Set, typename Fn>
0024 using check_has_member_remove_if_t =
0025 decltype(std::declval<Set>().remove_if(std::declval<Fn>()));
0026
0027 template <typename Set, typename Fn>
0028 static constexpr bool HasMemberRemoveIf =
0029 is_detected<check_has_member_remove_if_t, Set, Fn>::value;
0030
0031 template <typename Set>
0032 using check_has_member_erase_iter_t =
0033 decltype(std::declval<Set>().erase(std::declval<Set>().begin()));
0034
0035 template <typename Set>
0036 static constexpr bool HasMemberEraseIter =
0037 is_detected<check_has_member_erase_iter_t, Set>::value;
0038
0039 }
0040
0041
0042
0043 template <class S1Ty, class S2Ty> bool set_union(S1Ty &S1, const S2Ty &S2) {
0044 bool Changed = false;
0045
0046 for (const auto &E : S2)
0047 if (S1.insert(E).second)
0048 Changed = true;
0049
0050 return Changed;
0051 }
0052
0053
0054
0055
0056
0057
0058 template <class S1Ty, class S2Ty> void set_intersect(S1Ty &S1, const S2Ty &S2) {
0059 auto Pred = [&S2](const auto &E) { return !S2.count(E); };
0060 if constexpr (detail::HasMemberRemoveIf<S1Ty, decltype(Pred)>) {
0061 S1.remove_if(Pred);
0062 } else {
0063 typename S1Ty::iterator Next;
0064 for (typename S1Ty::iterator I = S1.begin(); I != S1.end(); I = Next) {
0065 Next = std::next(I);
0066 if (!S2.count(*I))
0067 S1.erase(I);
0068 }
0069 }
0070 }
0071
0072 template <class S1Ty, class S2Ty>
0073 S1Ty set_intersection_impl(const S1Ty &S1, const S2Ty &S2) {
0074 S1Ty Result;
0075 for (const auto &E : S1)
0076 if (S2.count(E))
0077 Result.insert(E);
0078 return Result;
0079 }
0080
0081
0082 template <class S1Ty, class S2Ty>
0083 S1Ty set_intersection(const S1Ty &S1, const S2Ty &S2) {
0084 if (S1.size() < S2.size())
0085 return set_intersection_impl(S1, S2);
0086 else
0087 return set_intersection_impl(S2, S1);
0088 }
0089
0090
0091
0092 template <class S1Ty, class S2Ty>
0093 S1Ty set_difference(const S1Ty &S1, const S2Ty &S2) {
0094 S1Ty Result;
0095 for (const auto &E : S1)
0096 if (!S2.count(E))
0097 Result.insert(E);
0098 return Result;
0099 }
0100
0101
0102
0103
0104
0105
0106 template <class S1Ty, class S2Ty> void set_subtract(S1Ty &S1, const S2Ty &S2) {
0107
0108
0109
0110 using ElemTy = decltype(*S1.begin());
0111 if constexpr (detail::HasMemberContains<S2Ty, ElemTy>) {
0112 auto Pred = [&S2](const auto &E) { return S2.contains(E); };
0113 if constexpr (detail::HasMemberRemoveIf<S1Ty, decltype(Pred)>) {
0114 if (S1.size() < S2.size()) {
0115 S1.remove_if(Pred);
0116 return;
0117 }
0118 } else if constexpr (detail::HasMemberEraseIter<S1Ty>) {
0119 if (S1.size() < S2.size()) {
0120 typename S1Ty::iterator Next;
0121 for (typename S1Ty::iterator SI = S1.begin(), SE = S1.end(); SI != SE;
0122 SI = Next) {
0123 Next = std::next(SI);
0124 if (S2.contains(*SI))
0125 S1.erase(SI);
0126 }
0127 return;
0128 }
0129 }
0130 }
0131
0132 for (const auto &E : S2)
0133 S1.erase(E);
0134 }
0135
0136
0137
0138
0139 template <class S1Ty, class S2Ty>
0140 void set_subtract(S1Ty &S1, const S2Ty &S2, S1Ty &Removed, S1Ty &Remaining) {
0141 for (const auto &E : S2)
0142 if (S1.erase(E))
0143 Removed.insert(E);
0144 else
0145 Remaining.insert(E);
0146 }
0147
0148
0149
0150 template <class S1Ty, class S2Ty>
0151 bool set_is_subset(const S1Ty &S1, const S2Ty &S2) {
0152 if (S1.size() > S2.size())
0153 return false;
0154 for (const auto It : S1)
0155 if (!S2.count(It))
0156 return false;
0157 return true;
0158 }
0159
0160 }
0161
0162 #endif