1 //===- llvm/ADT/SetVector.h - Set with insert order iteration ---*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements a set that has insertion order iteration 10 // characteristics. This is useful for keeping a set of things that need to be 11 // visited later but in a deterministic order (insertion order). The interface 12 // is purposefully minimal. 13 // 14 // This file defines SetVector and SmallSetVector, which performs no allocations 15 // if the SetVector has less than a certain number of elements. 16 // 17 //===----------------------------------------------------------------------===// 18 19 #ifndef LLVM_ADT_SETVECTOR_H 20 #define LLVM_ADT_SETVECTOR_H 21 22 #include "llvm/ADT/ArrayRef.h" 23 #include "llvm/ADT/DenseSet.h" 24 #include "llvm/ADT/STLExtras.h" 25 #include "llvm/Support/Compiler.h" 26 #include <cassert> 27 #include <iterator> 28 #include <vector> 29 30 namespace llvm { 31 32 /// A vector that has set insertion semantics. 33 /// 34 /// This adapter class provides a way to keep a set of things that also has the 35 /// property of a deterministic iteration order. The order of iteration is the 36 /// order of insertion. 37 template <typename T, typename Vector = std::vector<T>, 38 typename Set = DenseSet<T>> 39 class SetVector { 40 public: 41 using value_type = T; 42 using key_type = T; 43 using reference = T&; 44 using const_reference = const T&; 45 using set_type = Set; 46 using vector_type = Vector; 47 using iterator = typename vector_type::const_iterator; 48 using const_iterator = typename vector_type::const_iterator; 49 using reverse_iterator = typename vector_type::const_reverse_iterator; 50 using const_reverse_iterator = typename vector_type::const_reverse_iterator; 51 using size_type = typename vector_type::size_type; 52 53 /// Construct an empty SetVector 54 SetVector() = default; 55 56 /// Initialize a SetVector with a range of elements 57 template<typename It> 58 SetVector(It Start, It End) { 59 insert(Start, End); 60 } 61 62 ArrayRef<T> getArrayRef() const { return vector_; } 63 64 /// Clear the SetVector and return the underlying vector. 65 Vector takeVector() { 66 set_.clear(); 67 return std::move(vector_); 68 } 69 70 /// Determine if the SetVector is empty or not. 71 bool empty() const { 72 return vector_.empty(); 73 } 74 75 /// Determine the number of elements in the SetVector. 76 size_type size() const { 77 return vector_.size(); 78 } 79 80 /// Get an iterator to the beginning of the SetVector. 81 iterator begin() { 82 return vector_.begin(); 83 } 84 85 /// Get a const_iterator to the beginning of the SetVector. 86 const_iterator begin() const { 87 return vector_.begin(); 88 } 89 90 /// Get an iterator to the end of the SetVector. 91 iterator end() { 92 return vector_.end(); 93 } 94 95 /// Get a const_iterator to the end of the SetVector. 96 const_iterator end() const { 97 return vector_.end(); 98 } 99 100 /// Get an reverse_iterator to the end of the SetVector. 101 reverse_iterator rbegin() { 102 return vector_.rbegin(); 103 } 104 105 /// Get a const_reverse_iterator to the end of the SetVector. 106 const_reverse_iterator rbegin() const { 107 return vector_.rbegin(); 108 } 109 110 /// Get a reverse_iterator to the beginning of the SetVector. 111 reverse_iterator rend() { 112 return vector_.rend(); 113 } 114 115 /// Get a const_reverse_iterator to the beginning of the SetVector. 116 const_reverse_iterator rend() const { 117 return vector_.rend(); 118 } 119 120 /// Return the first element of the SetVector. 121 const T &front() const { 122 assert(!empty() && "Cannot call front() on empty SetVector!"); 123 return vector_.front(); 124 } 125 126 /// Return the last element of the SetVector. 127 const T &back() const { 128 assert(!empty() && "Cannot call back() on empty SetVector!"); 129 return vector_.back(); 130 } 131 132 /// Index into the SetVector. 133 const_reference operator[](size_type n) const { 134 assert(n < vector_.size() && "SetVector access out of range!"); 135 return vector_[n]; 136 } 137 138 /// Insert a new element into the SetVector. 139 /// \returns true if the element was inserted into the SetVector. 140 bool insert(const value_type &X) { 141 bool result = set_.insert(X).second; 142 if (result) 143 vector_.push_back(X); 144 return result; 145 } 146 147 /// Insert a range of elements into the SetVector. 148 template<typename It> 149 void insert(It Start, It End) { 150 for (; Start != End; ++Start) 151 if (set_.insert(*Start).second) 152 vector_.push_back(*Start); 153 } 154 155 /// Remove an item from the set vector. 156 bool remove(const value_type& X) { 157 if (set_.erase(X)) { 158 typename vector_type::iterator I = find(vector_, X); 159 assert(I != vector_.end() && "Corrupted SetVector instances!"); 160 vector_.erase(I); 161 return true; 162 } 163 return false; 164 } 165 166 /// Erase a single element from the set vector. 167 /// \returns an iterator pointing to the next element that followed the 168 /// element erased. This is the end of the SetVector if the last element is 169 /// erased. 170 iterator erase(iterator I) { 171 const key_type &V = *I; 172 assert(set_.count(V) && "Corrupted SetVector instances!"); 173 set_.erase(V); 174 175 // FIXME: No need to use the non-const iterator when built with 176 // std::vector.erase(const_iterator) as defined in C++11. This is for 177 // compatibility with non-standard libstdc++ up to 4.8 (fixed in 4.9). 178 auto NI = vector_.begin(); 179 std::advance(NI, std::distance<iterator>(NI, I)); 180 181 return vector_.erase(NI); 182 } 183 184 /// Remove items from the set vector based on a predicate function. 185 /// 186 /// This is intended to be equivalent to the following code, if we could 187 /// write it: 188 /// 189 /// \code 190 /// V.erase(remove_if(V, P), V.end()); 191 /// \endcode 192 /// 193 /// However, SetVector doesn't expose non-const iterators, making any 194 /// algorithm like remove_if impossible to use. 195 /// 196 /// \returns true if any element is removed. 197 template <typename UnaryPredicate> 198 bool remove_if(UnaryPredicate P) { 199 typename vector_type::iterator I = 200 llvm::remove_if(vector_, TestAndEraseFromSet<UnaryPredicate>(P, set_)); 201 if (I == vector_.end()) 202 return false; 203 vector_.erase(I, vector_.end()); 204 return true; 205 } 206 207 /// Check if the SetVector contains the given key. 208 bool contains(const key_type &key) const { 209 return set_.find(key) != set_.end(); 210 } 211 212 /// Count the number of elements of a given key in the SetVector. 213 /// \returns 0 if the element is not in the SetVector, 1 if it is. 214 size_type count(const key_type &key) const { 215 return set_.count(key); 216 } 217 218 /// Completely clear the SetVector 219 void clear() { 220 set_.clear(); 221 vector_.clear(); 222 } 223 224 /// Remove the last element of the SetVector. 225 void pop_back() { 226 assert(!empty() && "Cannot remove an element from an empty SetVector!"); 227 set_.erase(back()); 228 vector_.pop_back(); 229 } 230 231 LLVM_NODISCARD T pop_back_val() { 232 T Ret = back(); 233 pop_back(); 234 return Ret; 235 } 236 237 bool operator==(const SetVector &that) const { 238 return vector_ == that.vector_; 239 } 240 241 bool operator!=(const SetVector &that) const { 242 return vector_ != that.vector_; 243 } 244 245 /// Compute This := This u S, return whether 'This' changed. 246 /// TODO: We should be able to use set_union from SetOperations.h, but 247 /// SetVector interface is inconsistent with DenseSet. 248 template <class STy> 249 bool set_union(const STy &S) { 250 bool Changed = false; 251 252 for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE; 253 ++SI) 254 if (insert(*SI)) 255 Changed = true; 256 257 return Changed; 258 } 259 260 /// Compute This := This - B 261 /// TODO: We should be able to use set_subtract from SetOperations.h, but 262 /// SetVector interface is inconsistent with DenseSet. 263 template <class STy> 264 void set_subtract(const STy &S) { 265 for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE; 266 ++SI) 267 remove(*SI); 268 } 269 270 void swap(SetVector<T, Vector, Set> &RHS) { 271 set_.swap(RHS.set_); 272 vector_.swap(RHS.vector_); 273 } 274 275 private: 276 /// A wrapper predicate designed for use with std::remove_if. 277 /// 278 /// This predicate wraps a predicate suitable for use with std::remove_if to 279 /// call set_.erase(x) on each element which is slated for removal. 280 template <typename UnaryPredicate> 281 class TestAndEraseFromSet { 282 UnaryPredicate P; 283 set_type &set_; 284 285 public: 286 TestAndEraseFromSet(UnaryPredicate P, set_type &set_) 287 : P(std::move(P)), set_(set_) {} 288 289 template <typename ArgumentT> 290 bool operator()(const ArgumentT &Arg) { 291 if (P(Arg)) { 292 set_.erase(Arg); 293 return true; 294 } 295 return false; 296 } 297 }; 298 299 set_type set_; ///< The set. 300 vector_type vector_; ///< The vector. 301 }; 302 303 /// A SetVector that performs no allocations if smaller than 304 /// a certain size. 305 template <typename T, unsigned N> 306 class SmallSetVector 307 : public SetVector<T, SmallVector<T, N>, SmallDenseSet<T, N>> { 308 public: 309 SmallSetVector() = default; 310 311 /// Initialize a SmallSetVector with a range of elements 312 template<typename It> 313 SmallSetVector(It Start, It End) { 314 this->insert(Start, End); 315 } 316 }; 317 318 } // end namespace llvm 319 320 namespace std { 321 322 /// Implement std::swap in terms of SetVector swap. 323 template<typename T, typename V, typename S> 324 inline void 325 swap(llvm::SetVector<T, V, S> &LHS, llvm::SetVector<T, V, S> &RHS) { 326 LHS.swap(RHS); 327 } 328 329 /// Implement std::swap in terms of SmallSetVector swap. 330 template<typename T, unsigned N> 331 inline void 332 swap(llvm::SmallSetVector<T, N> &LHS, llvm::SmallSetVector<T, N> &RHS) { 333 LHS.swap(RHS); 334 } 335 336 } // end namespace std 337 338 #endif // LLVM_ADT_SETVECTOR_H 339