xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ADT/SetVector.h (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
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