//===- llvm/ADT/SmallSet.h - 'Normally small' sets --------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// /// \file /// This file defines the SmallSet class. /// //===----------------------------------------------------------------------===// #ifndef LLVM_ADT_SMALLSET_H #define LLVM_ADT_SMALLSET_H #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/iterator.h" #include <cstddef> #include <functional> #include <initializer_list> #include <set> #include <utility> namespace llvm { /// SmallSetIterator - This class implements a const_iterator for SmallSet by /// delegating to the underlying SmallVector or Set iterators. template <typename T, unsigned N, typename C> class SmallSetIterator : public iterator_facade_base<SmallSetIterator<T, N, C>, std::forward_iterator_tag, T> { … }; /// SmallSet - This maintains a set of unique values, optimizing for the case /// when the set is small (less than N). In this case, the set can be /// maintained with no mallocs. If the set gets large, we expand to using an /// std::set to maintain reasonable lookup times. template <typename T, unsigned N, typename C = std::less<T>> class SmallSet { /// Use a SmallVector to hold the elements here (even though it will never /// reach its 'large' stage) to avoid calling the default ctors of elements /// we will never use. SmallVector<T, N> Vector; std::set<T, C> Set; // In small mode SmallPtrSet uses linear search for the elements, so it is // not a good idea to choose this value too high. You may consider using a // DenseSet<> instead if you expect many elements in the set. static_assert(N <= 32, "N should be small"); public: using key_type = T; using size_type = size_t; using value_type = T; using const_iterator = SmallSetIterator<T, N, C>; SmallSet() = default; SmallSet(const SmallSet &) = default; SmallSet(SmallSet &&) = default; template <typename IterT> SmallSet(IterT Begin, IterT End) { … } template <typename RangeT> explicit SmallSet(const iterator_range<RangeT> &R) { … } SmallSet(std::initializer_list<T> L) { … } SmallSet &operator=(const SmallSet &) = default; SmallSet &operator=(SmallSet &&) = default; [[nodiscard]] bool empty() const { … } size_type size() const { … } /// count - Return 1 if the element is in the set, 0 otherwise. size_type count(const T &V) const { … } /// insert - Insert an element into the set if it isn't already there. /// Returns a pair. The first value of it is an iterator to the inserted /// element or the existing element in the set. The second value is true /// if the element is inserted (it was not in the set before). std::pair<const_iterator, bool> insert(const T &V) { … } std::pair<const_iterator, bool> insert(T &&V) { … } template <typename IterT> void insert(IterT I, IterT E) { … } bool erase(const T &V) { … } void clear() { … } const_iterator begin() const { … } const_iterator end() const { … } /// Check if the SmallSet contains the given element. bool contains(const T &V) const { … } private: bool isSmall() const { … } template <typename ArgType> std::pair<const_iterator, bool> insertImpl(ArgType &&V) { … } // Handwritten linear search. The use of std::find might hurt performance as // its implementation may be optimized for larger containers. typename SmallVector<T, N>::const_iterator vfind(const T &V) const { … } }; /// If this set is of pointer values, transparently switch over to using /// SmallPtrSet for performance. SmallSet<PointeeType *, N>; /// Equality comparison for SmallSet. /// /// Iterates over elements of LHS confirming that each element is also a member /// of RHS, and that RHS contains no additional values. /// Equivalent to N calls to RHS.count. /// For small-set mode amortized complexity is O(N^2) /// For large-set mode amortized complexity is linear, worst case is O(N^2) (if /// every hash collides). template <typename T, unsigned LN, unsigned RN, typename C> bool operator==(const SmallSet<T, LN, C> &LHS, const SmallSet<T, RN, C> &RHS) { … } /// Inequality comparison for SmallSet. /// /// Equivalent to !(LHS == RHS). See operator== for performance notes. template <typename T, unsigned LN, unsigned RN, typename C> bool operator!=(const SmallSet<T, LN, C> &LHS, const SmallSet<T, RN, C> &RHS) { … } } // end namespace llvm #endif // LLVM_ADT_SMALLSET_H