SetVector.h 9.4 KB

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