SetVector.h 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  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. // This file implements a set that has insertion order iteration
  15. // characteristics. This is useful for keeping a set of things that need to be
  16. // visited later but in a deterministic order (insertion order). The interface
  17. // is purposefully minimal.
  18. //
  19. // This file defines SetVector and SmallSetVector, which performs no allocations
  20. // if the SetVector has less than a certain number of elements.
  21. //
  22. //===----------------------------------------------------------------------===//
  23. #ifndef LLVM_ADT_SETVECTOR_H
  24. #define LLVM_ADT_SETVECTOR_H
  25. #include "llvm/ADT/ArrayRef.h"
  26. #include "llvm/ADT/DenseSet.h"
  27. #include "llvm/ADT/STLExtras.h"
  28. #include "llvm/Support/Compiler.h"
  29. #include <algorithm>
  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(iterator I) {
  152. const key_type &V = *I;
  153. assert(set_.count(V) && "Corrupted SetVector instances!");
  154. set_.erase(V);
  155. // FIXME: No need to use the non-const iterator when built with
  156. // std::vector.erase(const_iterator) as defined in C++11. This is for
  157. // compatibility with non-standard libstdc++ up to 4.8 (fixed in 4.9).
  158. auto NI = vector_.begin();
  159. std::advance(NI, std::distance<iterator>(NI, I));
  160. return vector_.erase(NI);
  161. }
  162. /// Remove items from the set vector based on a predicate function.
  163. ///
  164. /// This is intended to be equivalent to the following code, if we could
  165. /// write it:
  166. ///
  167. /// \code
  168. /// V.erase(remove_if(V, P), V.end());
  169. /// \endcode
  170. ///
  171. /// However, SetVector doesn't expose non-const iterators, making any
  172. /// algorithm like remove_if impossible to use.
  173. ///
  174. /// \returns true if any element is removed.
  175. template <typename UnaryPredicate>
  176. bool remove_if(UnaryPredicate P) {
  177. typename vector_type::iterator I =
  178. llvm::remove_if(vector_, TestAndEraseFromSet<UnaryPredicate>(P, set_));
  179. if (I == vector_.end())
  180. return false;
  181. vector_.erase(I, vector_.end());
  182. return true;
  183. }
  184. /// Check if the SetVector contains the given key.
  185. bool contains(const key_type &key) const {
  186. return set_.find(key) != set_.end();
  187. }
  188. /// Count the number of elements of a given key in the SetVector.
  189. /// \returns 0 if the element is not in the SetVector, 1 if it is.
  190. size_type count(const key_type &key) const {
  191. return set_.count(key);
  192. }
  193. /// Completely clear the SetVector
  194. void clear() {
  195. set_.clear();
  196. vector_.clear();
  197. }
  198. /// Remove the last element of the SetVector.
  199. void pop_back() {
  200. assert(!empty() && "Cannot remove an element from an empty SetVector!");
  201. set_.erase(back());
  202. vector_.pop_back();
  203. }
  204. LLVM_NODISCARD T pop_back_val() {
  205. T Ret = back();
  206. pop_back();
  207. return Ret;
  208. }
  209. bool operator==(const SetVector &that) const {
  210. return vector_ == that.vector_;
  211. }
  212. bool operator!=(const SetVector &that) const {
  213. return vector_ != that.vector_;
  214. }
  215. /// Compute This := This u S, return whether 'This' changed.
  216. /// TODO: We should be able to use set_union from SetOperations.h, but
  217. /// SetVector interface is inconsistent with DenseSet.
  218. template <class STy>
  219. bool set_union(const STy &S) {
  220. bool Changed = false;
  221. for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE;
  222. ++SI)
  223. if (insert(*SI))
  224. Changed = true;
  225. return Changed;
  226. }
  227. /// Compute This := This - B
  228. /// TODO: We should be able to use set_subtract from SetOperations.h, but
  229. /// SetVector interface is inconsistent with DenseSet.
  230. template <class STy>
  231. void set_subtract(const STy &S) {
  232. for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE;
  233. ++SI)
  234. remove(*SI);
  235. }
  236. void swap(SetVector<T, Vector, Set> &RHS) {
  237. set_.swap(RHS.set_);
  238. vector_.swap(RHS.vector_);
  239. }
  240. private:
  241. /// A wrapper predicate designed for use with std::remove_if.
  242. ///
  243. /// This predicate wraps a predicate suitable for use with std::remove_if to
  244. /// call set_.erase(x) on each element which is slated for removal.
  245. template <typename UnaryPredicate>
  246. class TestAndEraseFromSet {
  247. UnaryPredicate P;
  248. set_type &set_;
  249. public:
  250. TestAndEraseFromSet(UnaryPredicate P, set_type &set_)
  251. : P(std::move(P)), set_(set_) {}
  252. template <typename ArgumentT>
  253. bool operator()(const ArgumentT &Arg) {
  254. if (P(Arg)) {
  255. set_.erase(Arg);
  256. return true;
  257. }
  258. return false;
  259. }
  260. };
  261. set_type set_; ///< The set.
  262. vector_type vector_; ///< The vector.
  263. };
  264. /// A SetVector that performs no allocations if smaller than
  265. /// a certain size.
  266. template <typename T, unsigned N>
  267. class SmallSetVector
  268. : public SetVector<T, SmallVector<T, N>, SmallDenseSet<T, N>> {
  269. public:
  270. SmallSetVector() = default;
  271. /// Initialize a SmallSetVector with a range of elements
  272. template<typename It>
  273. SmallSetVector(It Start, It End) {
  274. this->insert(Start, End);
  275. }
  276. };
  277. } // end namespace llvm
  278. namespace std {
  279. /// Implement std::swap in terms of SetVector swap.
  280. template<typename T, typename V, typename S>
  281. inline void
  282. swap(llvm::SetVector<T, V, S> &LHS, llvm::SetVector<T, V, S> &RHS) {
  283. LHS.swap(RHS);
  284. }
  285. /// Implement std::swap in terms of SmallSetVector swap.
  286. template<typename T, unsigned N>
  287. inline void
  288. swap(llvm::SmallSetVector<T, N> &LHS, llvm::SmallSetVector<T, N> &RHS) {
  289. LHS.swap(RHS);
  290. }
  291. } // end namespace std
  292. #endif // LLVM_ADT_SETVECTOR_H
  293. #ifdef __GNUC__
  294. #pragma GCC diagnostic pop
  295. #endif