10b57cec5SDimitry Andric //===- llvm/ADT/SetVector.h - Set with insert order iteration ---*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 81fd87a68SDimitry Andric /// 91fd87a68SDimitry Andric /// \file 101fd87a68SDimitry Andric /// This file implements a set that has insertion order iteration 111fd87a68SDimitry Andric /// characteristics. This is useful for keeping a set of things that need to be 121fd87a68SDimitry Andric /// visited later but in a deterministic order (insertion order). The interface 131fd87a68SDimitry Andric /// is purposefully minimal. 141fd87a68SDimitry Andric /// 151fd87a68SDimitry Andric /// This file defines SetVector and SmallSetVector, which performs no 161fd87a68SDimitry Andric /// allocations if the SetVector has less than a certain number of elements. 171fd87a68SDimitry Andric /// 180b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 190b57cec5SDimitry Andric 200b57cec5SDimitry Andric #ifndef LLVM_ADT_SETVECTOR_H 210b57cec5SDimitry Andric #define LLVM_ADT_SETVECTOR_H 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 240b57cec5SDimitry Andric #include "llvm/ADT/DenseSet.h" 250b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h" 265f757f3fSDimitry Andric #include "llvm/ADT/SmallVector.h" 270b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 280b57cec5SDimitry Andric #include <cassert> 290b57cec5SDimitry Andric #include <iterator> 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric namespace llvm { 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric /// A vector that has set insertion semantics. 340b57cec5SDimitry Andric /// 350b57cec5SDimitry Andric /// This adapter class provides a way to keep a set of things that also has the 360b57cec5SDimitry Andric /// property of a deterministic iteration order. The order of iteration is the 370b57cec5SDimitry Andric /// order of insertion. 3806c3fb27SDimitry Andric /// 3906c3fb27SDimitry Andric /// The key and value types are derived from the Set and Vector types 4006c3fb27SDimitry Andric /// respectively. This allows the vector-type operations and set-type operations 4106c3fb27SDimitry Andric /// to have different types. In particular, this is useful when storing pointers 4206c3fb27SDimitry Andric /// as "Foo *" values but looking them up as "const Foo *" keys. 4306c3fb27SDimitry Andric /// 4406c3fb27SDimitry Andric /// No constraint is placed on the key and value types, although it is assumed 4506c3fb27SDimitry Andric /// that value_type can be converted into key_type for insertion. Users must be 4606c3fb27SDimitry Andric /// aware of any loss of information in this conversion. For example, setting 4706c3fb27SDimitry Andric /// value_type to float and key_type to int can produce very surprising results, 4806c3fb27SDimitry Andric /// but it is not explicitly disallowed. 4906c3fb27SDimitry Andric /// 5006c3fb27SDimitry Andric /// The parameter N specifies the "small" size of the container, which is the 5106c3fb27SDimitry Andric /// number of elements upto which a linear scan over the Vector will be used 5206c3fb27SDimitry Andric /// when searching for elements instead of checking Set, due to it being better 5306c3fb27SDimitry Andric /// for performance. A value of 0 means that this mode of operation is not used, 5406c3fb27SDimitry Andric /// and is the default value. 555f757f3fSDimitry Andric template <typename T, typename Vector = SmallVector<T, 0>, 5606c3fb27SDimitry Andric typename Set = DenseSet<T>, unsigned N = 0> 570b57cec5SDimitry Andric class SetVector { 5806c3fb27SDimitry Andric // Much like in SmallPtrSet, this value should not be too high to prevent 5906c3fb27SDimitry Andric // excessively long linear scans from occuring. 6006c3fb27SDimitry Andric static_assert(N <= 32, "Small size should be less than or equal to 32!"); 6106c3fb27SDimitry Andric 620b57cec5SDimitry Andric public: 6306c3fb27SDimitry Andric using value_type = typename Vector::value_type; 6406c3fb27SDimitry Andric using key_type = typename Set::key_type; 6506c3fb27SDimitry Andric using reference = value_type &; 6606c3fb27SDimitry Andric using const_reference = const value_type &; 670b57cec5SDimitry Andric using set_type = Set; 680b57cec5SDimitry Andric using vector_type = Vector; 690b57cec5SDimitry Andric using iterator = typename vector_type::const_iterator; 700b57cec5SDimitry Andric using const_iterator = typename vector_type::const_iterator; 710b57cec5SDimitry Andric using reverse_iterator = typename vector_type::const_reverse_iterator; 720b57cec5SDimitry Andric using const_reverse_iterator = typename vector_type::const_reverse_iterator; 730b57cec5SDimitry Andric using size_type = typename vector_type::size_type; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric /// Construct an empty SetVector 760b57cec5SDimitry Andric SetVector() = default; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric /// Initialize a SetVector with a range of elements 790b57cec5SDimitry Andric template<typename It> 800b57cec5SDimitry Andric SetVector(It Start, It End) { 810b57cec5SDimitry Andric insert(Start, End); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 8406c3fb27SDimitry Andric ArrayRef<value_type> getArrayRef() const { return vector_; } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric /// Clear the SetVector and return the underlying vector. 870b57cec5SDimitry Andric Vector takeVector() { 880b57cec5SDimitry Andric set_.clear(); 890b57cec5SDimitry Andric return std::move(vector_); 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric /// Determine if the SetVector is empty or not. 930b57cec5SDimitry Andric bool empty() const { 940b57cec5SDimitry Andric return vector_.empty(); 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric /// Determine the number of elements in the SetVector. 980b57cec5SDimitry Andric size_type size() const { 990b57cec5SDimitry Andric return vector_.size(); 1000b57cec5SDimitry Andric } 1010b57cec5SDimitry Andric 1020b57cec5SDimitry Andric /// Get an iterator to the beginning of the SetVector. 1030b57cec5SDimitry Andric iterator begin() { 1040b57cec5SDimitry Andric return vector_.begin(); 1050b57cec5SDimitry Andric } 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric /// Get a const_iterator to the beginning of the SetVector. 1080b57cec5SDimitry Andric const_iterator begin() const { 1090b57cec5SDimitry Andric return vector_.begin(); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric /// Get an iterator to the end of the SetVector. 1130b57cec5SDimitry Andric iterator end() { 1140b57cec5SDimitry Andric return vector_.end(); 1150b57cec5SDimitry Andric } 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric /// Get a const_iterator to the end of the SetVector. 1180b57cec5SDimitry Andric const_iterator end() const { 1190b57cec5SDimitry Andric return vector_.end(); 1200b57cec5SDimitry Andric } 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric /// Get an reverse_iterator to the end of the SetVector. 1230b57cec5SDimitry Andric reverse_iterator rbegin() { 1240b57cec5SDimitry Andric return vector_.rbegin(); 1250b57cec5SDimitry Andric } 1260b57cec5SDimitry Andric 1270b57cec5SDimitry Andric /// Get a const_reverse_iterator to the end of the SetVector. 1280b57cec5SDimitry Andric const_reverse_iterator rbegin() const { 1290b57cec5SDimitry Andric return vector_.rbegin(); 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric 1320b57cec5SDimitry Andric /// Get a reverse_iterator to the beginning of the SetVector. 1330b57cec5SDimitry Andric reverse_iterator rend() { 1340b57cec5SDimitry Andric return vector_.rend(); 1350b57cec5SDimitry Andric } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric /// Get a const_reverse_iterator to the beginning of the SetVector. 1380b57cec5SDimitry Andric const_reverse_iterator rend() const { 1390b57cec5SDimitry Andric return vector_.rend(); 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric /// Return the first element of the SetVector. 14306c3fb27SDimitry Andric const value_type &front() const { 1440b57cec5SDimitry Andric assert(!empty() && "Cannot call front() on empty SetVector!"); 1450b57cec5SDimitry Andric return vector_.front(); 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric /// Return the last element of the SetVector. 14906c3fb27SDimitry Andric const value_type &back() const { 1500b57cec5SDimitry Andric assert(!empty() && "Cannot call back() on empty SetVector!"); 1510b57cec5SDimitry Andric return vector_.back(); 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric /// Index into the SetVector. 1550b57cec5SDimitry Andric const_reference operator[](size_type n) const { 1560b57cec5SDimitry Andric assert(n < vector_.size() && "SetVector access out of range!"); 1570b57cec5SDimitry Andric return vector_[n]; 1580b57cec5SDimitry Andric } 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric /// Insert a new element into the SetVector. 1610b57cec5SDimitry Andric /// \returns true if the element was inserted into the SetVector. 1620b57cec5SDimitry Andric bool insert(const value_type &X) { 16306c3fb27SDimitry Andric if constexpr (canBeSmall()) 16406c3fb27SDimitry Andric if (isSmall()) { 165*7a6dacacSDimitry Andric if (!llvm::is_contained(vector_, X)) { 16606c3fb27SDimitry Andric vector_.push_back(X); 16706c3fb27SDimitry Andric if (vector_.size() > N) 16806c3fb27SDimitry Andric makeBig(); 16906c3fb27SDimitry Andric return true; 17006c3fb27SDimitry Andric } 17106c3fb27SDimitry Andric return false; 17206c3fb27SDimitry Andric } 17306c3fb27SDimitry Andric 1740b57cec5SDimitry Andric bool result = set_.insert(X).second; 1750b57cec5SDimitry Andric if (result) 1760b57cec5SDimitry Andric vector_.push_back(X); 1770b57cec5SDimitry Andric return result; 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric /// Insert a range of elements into the SetVector. 1810b57cec5SDimitry Andric template<typename It> 1820b57cec5SDimitry Andric void insert(It Start, It End) { 1830b57cec5SDimitry Andric for (; Start != End; ++Start) 18406c3fb27SDimitry Andric insert(*Start); 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric /// Remove an item from the set vector. 1880b57cec5SDimitry Andric bool remove(const value_type& X) { 18906c3fb27SDimitry Andric if constexpr (canBeSmall()) 19006c3fb27SDimitry Andric if (isSmall()) { 19106c3fb27SDimitry Andric typename vector_type::iterator I = find(vector_, X); 19206c3fb27SDimitry Andric if (I != vector_.end()) { 19306c3fb27SDimitry Andric vector_.erase(I); 19406c3fb27SDimitry Andric return true; 19506c3fb27SDimitry Andric } 19606c3fb27SDimitry Andric return false; 19706c3fb27SDimitry Andric } 19806c3fb27SDimitry Andric 1990b57cec5SDimitry Andric if (set_.erase(X)) { 2000b57cec5SDimitry Andric typename vector_type::iterator I = find(vector_, X); 2010b57cec5SDimitry Andric assert(I != vector_.end() && "Corrupted SetVector instances!"); 2020b57cec5SDimitry Andric vector_.erase(I); 2030b57cec5SDimitry Andric return true; 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric return false; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric /// Erase a single element from the set vector. 2090b57cec5SDimitry Andric /// \returns an iterator pointing to the next element that followed the 2100b57cec5SDimitry Andric /// element erased. This is the end of the SetVector if the last element is 2110b57cec5SDimitry Andric /// erased. 212bdd1243dSDimitry Andric iterator erase(const_iterator I) { 21306c3fb27SDimitry Andric if constexpr (canBeSmall()) 21406c3fb27SDimitry Andric if (isSmall()) 21506c3fb27SDimitry Andric return vector_.erase(I); 21606c3fb27SDimitry Andric 2170b57cec5SDimitry Andric const key_type &V = *I; 2180b57cec5SDimitry Andric assert(set_.count(V) && "Corrupted SetVector instances!"); 2190b57cec5SDimitry Andric set_.erase(V); 220bdd1243dSDimitry Andric return vector_.erase(I); 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric /// Remove items from the set vector based on a predicate function. 2240b57cec5SDimitry Andric /// 2250b57cec5SDimitry Andric /// This is intended to be equivalent to the following code, if we could 2260b57cec5SDimitry Andric /// write it: 2270b57cec5SDimitry Andric /// 2280b57cec5SDimitry Andric /// \code 2290b57cec5SDimitry Andric /// V.erase(remove_if(V, P), V.end()); 2300b57cec5SDimitry Andric /// \endcode 2310b57cec5SDimitry Andric /// 2320b57cec5SDimitry Andric /// However, SetVector doesn't expose non-const iterators, making any 2330b57cec5SDimitry Andric /// algorithm like remove_if impossible to use. 2340b57cec5SDimitry Andric /// 2350b57cec5SDimitry Andric /// \returns true if any element is removed. 2360b57cec5SDimitry Andric template <typename UnaryPredicate> 2370b57cec5SDimitry Andric bool remove_if(UnaryPredicate P) { 23806c3fb27SDimitry Andric typename vector_type::iterator I = [this, P] { 23906c3fb27SDimitry Andric if constexpr (canBeSmall()) 24006c3fb27SDimitry Andric if (isSmall()) 24106c3fb27SDimitry Andric return llvm::remove_if(vector_, P); 24206c3fb27SDimitry Andric 24306c3fb27SDimitry Andric return llvm::remove_if(vector_, 24406c3fb27SDimitry Andric TestAndEraseFromSet<UnaryPredicate>(P, set_)); 24506c3fb27SDimitry Andric }(); 24606c3fb27SDimitry Andric 2470b57cec5SDimitry Andric if (I == vector_.end()) 2480b57cec5SDimitry Andric return false; 2490b57cec5SDimitry Andric vector_.erase(I, vector_.end()); 2500b57cec5SDimitry Andric return true; 2510b57cec5SDimitry Andric } 2520b57cec5SDimitry Andric 253e8d8bef9SDimitry Andric /// Check if the SetVector contains the given key. 254e8d8bef9SDimitry Andric bool contains(const key_type &key) const { 25506c3fb27SDimitry Andric if constexpr (canBeSmall()) 25606c3fb27SDimitry Andric if (isSmall()) 25706c3fb27SDimitry Andric return is_contained(vector_, key); 25806c3fb27SDimitry Andric 259e8d8bef9SDimitry Andric return set_.find(key) != set_.end(); 260e8d8bef9SDimitry Andric } 261e8d8bef9SDimitry Andric 2620b57cec5SDimitry Andric /// Count the number of elements of a given key in the SetVector. 2630b57cec5SDimitry Andric /// \returns 0 if the element is not in the SetVector, 1 if it is. 2640b57cec5SDimitry Andric size_type count(const key_type &key) const { 26506c3fb27SDimitry Andric if constexpr (canBeSmall()) 26606c3fb27SDimitry Andric if (isSmall()) 26706c3fb27SDimitry Andric return is_contained(vector_, key); 26806c3fb27SDimitry Andric 2690b57cec5SDimitry Andric return set_.count(key); 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric /// Completely clear the SetVector 2730b57cec5SDimitry Andric void clear() { 2740b57cec5SDimitry Andric set_.clear(); 2750b57cec5SDimitry Andric vector_.clear(); 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric 2780b57cec5SDimitry Andric /// Remove the last element of the SetVector. 2790b57cec5SDimitry Andric void pop_back() { 2800b57cec5SDimitry Andric assert(!empty() && "Cannot remove an element from an empty SetVector!"); 2810b57cec5SDimitry Andric set_.erase(back()); 2820b57cec5SDimitry Andric vector_.pop_back(); 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric 28506c3fb27SDimitry Andric [[nodiscard]] value_type pop_back_val() { 28606c3fb27SDimitry Andric value_type Ret = back(); 2870b57cec5SDimitry Andric pop_back(); 2880b57cec5SDimitry Andric return Ret; 2890b57cec5SDimitry Andric } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric bool operator==(const SetVector &that) const { 2920b57cec5SDimitry Andric return vector_ == that.vector_; 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric bool operator!=(const SetVector &that) const { 2960b57cec5SDimitry Andric return vector_ != that.vector_; 2970b57cec5SDimitry Andric } 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric /// Compute This := This u S, return whether 'This' changed. 3000b57cec5SDimitry Andric /// TODO: We should be able to use set_union from SetOperations.h, but 3010b57cec5SDimitry Andric /// SetVector interface is inconsistent with DenseSet. 3020b57cec5SDimitry Andric template <class STy> 3030b57cec5SDimitry Andric bool set_union(const STy &S) { 3040b57cec5SDimitry Andric bool Changed = false; 3050b57cec5SDimitry Andric 3060b57cec5SDimitry Andric for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE; 3070b57cec5SDimitry Andric ++SI) 3080b57cec5SDimitry Andric if (insert(*SI)) 3090b57cec5SDimitry Andric Changed = true; 3100b57cec5SDimitry Andric 3110b57cec5SDimitry Andric return Changed; 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric /// Compute This := This - B 3150b57cec5SDimitry Andric /// TODO: We should be able to use set_subtract from SetOperations.h, but 3160b57cec5SDimitry Andric /// SetVector interface is inconsistent with DenseSet. 3170b57cec5SDimitry Andric template <class STy> 3180b57cec5SDimitry Andric void set_subtract(const STy &S) { 3190b57cec5SDimitry Andric for (typename STy::const_iterator SI = S.begin(), SE = S.end(); SI != SE; 3200b57cec5SDimitry Andric ++SI) 3210b57cec5SDimitry Andric remove(*SI); 3220b57cec5SDimitry Andric } 3230b57cec5SDimitry Andric 32406c3fb27SDimitry Andric void swap(SetVector<T, Vector, Set, N> &RHS) { 3255ffd83dbSDimitry Andric set_.swap(RHS.set_); 3265ffd83dbSDimitry Andric vector_.swap(RHS.vector_); 3275ffd83dbSDimitry Andric } 3285ffd83dbSDimitry Andric 3290b57cec5SDimitry Andric private: 3300b57cec5SDimitry Andric /// A wrapper predicate designed for use with std::remove_if. 3310b57cec5SDimitry Andric /// 3320b57cec5SDimitry Andric /// This predicate wraps a predicate suitable for use with std::remove_if to 3330b57cec5SDimitry Andric /// call set_.erase(x) on each element which is slated for removal. 3340b57cec5SDimitry Andric template <typename UnaryPredicate> 3350b57cec5SDimitry Andric class TestAndEraseFromSet { 3360b57cec5SDimitry Andric UnaryPredicate P; 3370b57cec5SDimitry Andric set_type &set_; 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric public: 3400b57cec5SDimitry Andric TestAndEraseFromSet(UnaryPredicate P, set_type &set_) 3410b57cec5SDimitry Andric : P(std::move(P)), set_(set_) {} 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric template <typename ArgumentT> 3440b57cec5SDimitry Andric bool operator()(const ArgumentT &Arg) { 3450b57cec5SDimitry Andric if (P(Arg)) { 3460b57cec5SDimitry Andric set_.erase(Arg); 3470b57cec5SDimitry Andric return true; 3480b57cec5SDimitry Andric } 3490b57cec5SDimitry Andric return false; 3500b57cec5SDimitry Andric } 3510b57cec5SDimitry Andric }; 3520b57cec5SDimitry Andric 35306c3fb27SDimitry Andric [[nodiscard]] static constexpr bool canBeSmall() { return N != 0; } 35406c3fb27SDimitry Andric 35506c3fb27SDimitry Andric [[nodiscard]] bool isSmall() const { return set_.empty(); } 35606c3fb27SDimitry Andric 35706c3fb27SDimitry Andric void makeBig() { 35806c3fb27SDimitry Andric if constexpr (canBeSmall()) 35906c3fb27SDimitry Andric for (const auto &entry : vector_) 36006c3fb27SDimitry Andric set_.insert(entry); 36106c3fb27SDimitry Andric } 36206c3fb27SDimitry Andric 3630b57cec5SDimitry Andric set_type set_; ///< The set. 3640b57cec5SDimitry Andric vector_type vector_; ///< The vector. 3650b57cec5SDimitry Andric }; 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric /// A SetVector that performs no allocations if smaller than 3680b57cec5SDimitry Andric /// a certain size. 3690b57cec5SDimitry Andric template <typename T, unsigned N> 37006c3fb27SDimitry Andric class SmallSetVector : public SetVector<T, SmallVector<T, N>, DenseSet<T>, N> { 3710b57cec5SDimitry Andric public: 3720b57cec5SDimitry Andric SmallSetVector() = default; 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric /// Initialize a SmallSetVector with a range of elements 3750b57cec5SDimitry Andric template<typename It> 3760b57cec5SDimitry Andric SmallSetVector(It Start, It End) { 3770b57cec5SDimitry Andric this->insert(Start, End); 3780b57cec5SDimitry Andric } 3790b57cec5SDimitry Andric }; 3800b57cec5SDimitry Andric 3810b57cec5SDimitry Andric } // end namespace llvm 3820b57cec5SDimitry Andric 3835ffd83dbSDimitry Andric namespace std { 3845ffd83dbSDimitry Andric 3855ffd83dbSDimitry Andric /// Implement std::swap in terms of SetVector swap. 38606c3fb27SDimitry Andric template <typename T, typename V, typename S, unsigned N> 38706c3fb27SDimitry Andric inline void swap(llvm::SetVector<T, V, S, N> &LHS, 38806c3fb27SDimitry Andric llvm::SetVector<T, V, S, N> &RHS) { 3895ffd83dbSDimitry Andric LHS.swap(RHS); 3905ffd83dbSDimitry Andric } 3915ffd83dbSDimitry Andric 3925ffd83dbSDimitry Andric /// Implement std::swap in terms of SmallSetVector swap. 3935ffd83dbSDimitry Andric template<typename T, unsigned N> 3945ffd83dbSDimitry Andric inline void 3955ffd83dbSDimitry Andric swap(llvm::SmallSetVector<T, N> &LHS, llvm::SmallSetVector<T, N> &RHS) { 3965ffd83dbSDimitry Andric LHS.swap(RHS); 3975ffd83dbSDimitry Andric } 3985ffd83dbSDimitry Andric 3995ffd83dbSDimitry Andric } // end namespace std 4005ffd83dbSDimitry Andric 4010b57cec5SDimitry Andric #endif // LLVM_ADT_SETVECTOR_H 402