10b57cec5SDimitry Andric //===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- 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 //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains some templates that are useful if you are working with the 100b57cec5SDimitry Andric // STL at all. 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric // No library is required when using these functions. 130b57cec5SDimitry Andric // 140b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #ifndef LLVM_ADT_STLEXTRAS_H 170b57cec5SDimitry Andric #define LLVM_ADT_STLEXTRAS_H 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 200b57cec5SDimitry Andric #include "llvm/ADT/iterator.h" 210b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 220b57cec5SDimitry Andric #include "llvm/Config/abi-breaking.h" 230b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 240b57cec5SDimitry Andric #include <algorithm> 250b57cec5SDimitry Andric #include <cassert> 260b57cec5SDimitry Andric #include <cstddef> 270b57cec5SDimitry Andric #include <cstdint> 280b57cec5SDimitry Andric #include <cstdlib> 290b57cec5SDimitry Andric #include <functional> 300b57cec5SDimitry Andric #include <initializer_list> 310b57cec5SDimitry Andric #include <iterator> 320b57cec5SDimitry Andric #include <limits> 330b57cec5SDimitry Andric #include <memory> 340b57cec5SDimitry Andric #include <tuple> 350b57cec5SDimitry Andric #include <type_traits> 360b57cec5SDimitry Andric #include <utility> 370b57cec5SDimitry Andric 380b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 390b57cec5SDimitry Andric #include <random> // for std::mt19937 400b57cec5SDimitry Andric #endif 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric namespace llvm { 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric // Only used by compiler if both template types are the same. Useful when 450b57cec5SDimitry Andric // using SFINAE to test for the existence of member functions. 460b57cec5SDimitry Andric template <typename T, T> struct SameType; 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric namespace detail { 490b57cec5SDimitry Andric 500b57cec5SDimitry Andric template <typename RangeT> 510b57cec5SDimitry Andric using IterOfRange = decltype(std::begin(std::declval<RangeT &>())); 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric } // end namespace detail 540b57cec5SDimitry Andric 550b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 560b57cec5SDimitry Andric // Extra additions to <type_traits> 570b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric template <typename T> 600b57cec5SDimitry Andric struct negation : std::integral_constant<bool, !bool(T::value)> {}; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric template <typename...> struct conjunction : std::true_type {}; 630b57cec5SDimitry Andric template <typename B1> struct conjunction<B1> : B1 {}; 640b57cec5SDimitry Andric template <typename B1, typename... Bn> 650b57cec5SDimitry Andric struct conjunction<B1, Bn...> 660b57cec5SDimitry Andric : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {}; 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric template <typename T> struct make_const_ptr { 690b57cec5SDimitry Andric using type = 700b57cec5SDimitry Andric typename std::add_pointer<typename std::add_const<T>::type>::type; 710b57cec5SDimitry Andric }; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric template <typename T> struct make_const_ref { 740b57cec5SDimitry Andric using type = typename std::add_lvalue_reference< 750b57cec5SDimitry Andric typename std::add_const<T>::type>::type; 760b57cec5SDimitry Andric }; 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 790b57cec5SDimitry Andric // Extra additions to <functional> 800b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric template <class Ty> struct identity { 830b57cec5SDimitry Andric using argument_type = Ty; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric Ty &operator()(Ty &self) const { 860b57cec5SDimitry Andric return self; 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric const Ty &operator()(const Ty &self) const { 890b57cec5SDimitry Andric return self; 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric }; 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric /// An efficient, type-erasing, non-owning reference to a callable. This is 940b57cec5SDimitry Andric /// intended for use as the type of a function parameter that is not used 950b57cec5SDimitry Andric /// after the function in question returns. 960b57cec5SDimitry Andric /// 970b57cec5SDimitry Andric /// This class does not own the callable, so it is not in general safe to store 980b57cec5SDimitry Andric /// a function_ref. 990b57cec5SDimitry Andric template<typename Fn> class function_ref; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric template<typename Ret, typename ...Params> 1020b57cec5SDimitry Andric class function_ref<Ret(Params...)> { 1030b57cec5SDimitry Andric Ret (*callback)(intptr_t callable, Params ...params) = nullptr; 1040b57cec5SDimitry Andric intptr_t callable; 1050b57cec5SDimitry Andric 1060b57cec5SDimitry Andric template<typename Callable> 1070b57cec5SDimitry Andric static Ret callback_fn(intptr_t callable, Params ...params) { 1080b57cec5SDimitry Andric return (*reinterpret_cast<Callable*>(callable))( 1090b57cec5SDimitry Andric std::forward<Params>(params)...); 1100b57cec5SDimitry Andric } 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric public: 1130b57cec5SDimitry Andric function_ref() = default; 1140b57cec5SDimitry Andric function_ref(std::nullptr_t) {} 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric template <typename Callable> 1170b57cec5SDimitry Andric function_ref(Callable &&callable, 1180b57cec5SDimitry Andric typename std::enable_if< 1190b57cec5SDimitry Andric !std::is_same<typename std::remove_reference<Callable>::type, 1200b57cec5SDimitry Andric function_ref>::value>::type * = nullptr) 1210b57cec5SDimitry Andric : callback(callback_fn<typename std::remove_reference<Callable>::type>), 1220b57cec5SDimitry Andric callable(reinterpret_cast<intptr_t>(&callable)) {} 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric Ret operator()(Params ...params) const { 1250b57cec5SDimitry Andric return callback(callable, std::forward<Params>(params)...); 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric operator bool() const { return callback; } 1290b57cec5SDimitry Andric }; 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric // deleter - Very very very simple method that is used to invoke operator 1320b57cec5SDimitry Andric // delete on something. It is used like this: 1330b57cec5SDimitry Andric // 1340b57cec5SDimitry Andric // for_each(V.begin(), B.end(), deleter<Interval>); 1350b57cec5SDimitry Andric template <class T> 1360b57cec5SDimitry Andric inline void deleter(T *Ptr) { 1370b57cec5SDimitry Andric delete Ptr; 1380b57cec5SDimitry Andric } 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1410b57cec5SDimitry Andric // Extra additions to <iterator> 1420b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric namespace adl_detail { 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric using std::begin; 1470b57cec5SDimitry Andric 1480b57cec5SDimitry Andric template <typename ContainerTy> 1490b57cec5SDimitry Andric auto adl_begin(ContainerTy &&container) 1500b57cec5SDimitry Andric -> decltype(begin(std::forward<ContainerTy>(container))) { 1510b57cec5SDimitry Andric return begin(std::forward<ContainerTy>(container)); 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric using std::end; 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric template <typename ContainerTy> 1570b57cec5SDimitry Andric auto adl_end(ContainerTy &&container) 1580b57cec5SDimitry Andric -> decltype(end(std::forward<ContainerTy>(container))) { 1590b57cec5SDimitry Andric return end(std::forward<ContainerTy>(container)); 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric using std::swap; 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric template <typename T> 1650b57cec5SDimitry Andric void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(), 1660b57cec5SDimitry Andric std::declval<T>()))) { 1670b57cec5SDimitry Andric swap(std::forward<T>(lhs), std::forward<T>(rhs)); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric } // end namespace adl_detail 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric template <typename ContainerTy> 1730b57cec5SDimitry Andric auto adl_begin(ContainerTy &&container) 1740b57cec5SDimitry Andric -> decltype(adl_detail::adl_begin(std::forward<ContainerTy>(container))) { 1750b57cec5SDimitry Andric return adl_detail::adl_begin(std::forward<ContainerTy>(container)); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric template <typename ContainerTy> 1790b57cec5SDimitry Andric auto adl_end(ContainerTy &&container) 1800b57cec5SDimitry Andric -> decltype(adl_detail::adl_end(std::forward<ContainerTy>(container))) { 1810b57cec5SDimitry Andric return adl_detail::adl_end(std::forward<ContainerTy>(container)); 1820b57cec5SDimitry Andric } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric template <typename T> 1850b57cec5SDimitry Andric void adl_swap(T &&lhs, T &&rhs) noexcept( 1860b57cec5SDimitry Andric noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) { 1870b57cec5SDimitry Andric adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs)); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric /// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty. 1910b57cec5SDimitry Andric template <typename T> 1920b57cec5SDimitry Andric constexpr bool empty(const T &RangeOrContainer) { 1930b57cec5SDimitry Andric return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer); 1940b57cec5SDimitry Andric } 1950b57cec5SDimitry Andric 196*480093f4SDimitry Andric /// Return a range covering \p RangeOrContainer with the first N elements 197*480093f4SDimitry Andric /// excluded. 198*480093f4SDimitry Andric template <typename T> 199*480093f4SDimitry Andric auto drop_begin(T &&RangeOrContainer, size_t N) -> 200*480093f4SDimitry Andric iterator_range<decltype(adl_begin(RangeOrContainer))> { 201*480093f4SDimitry Andric return make_range(std::next(adl_begin(RangeOrContainer), N), 202*480093f4SDimitry Andric adl_end(RangeOrContainer)); 203*480093f4SDimitry Andric } 204*480093f4SDimitry Andric 2050b57cec5SDimitry Andric // mapped_iterator - This is a simple iterator adapter that causes a function to 2060b57cec5SDimitry Andric // be applied whenever operator* is invoked on the iterator. 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric template <typename ItTy, typename FuncTy, 2090b57cec5SDimitry Andric typename FuncReturnTy = 2100b57cec5SDimitry Andric decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))> 2110b57cec5SDimitry Andric class mapped_iterator 2120b57cec5SDimitry Andric : public iterator_adaptor_base< 2130b57cec5SDimitry Andric mapped_iterator<ItTy, FuncTy>, ItTy, 2140b57cec5SDimitry Andric typename std::iterator_traits<ItTy>::iterator_category, 2150b57cec5SDimitry Andric typename std::remove_reference<FuncReturnTy>::type> { 2160b57cec5SDimitry Andric public: 2170b57cec5SDimitry Andric mapped_iterator(ItTy U, FuncTy F) 2180b57cec5SDimitry Andric : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {} 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric ItTy getCurrent() { return this->I; } 2210b57cec5SDimitry Andric 2220b57cec5SDimitry Andric FuncReturnTy operator*() { return F(*this->I); } 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric private: 2250b57cec5SDimitry Andric FuncTy F; 2260b57cec5SDimitry Andric }; 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric // map_iterator - Provide a convenient way to create mapped_iterators, just like 2290b57cec5SDimitry Andric // make_pair is useful for creating pairs... 2300b57cec5SDimitry Andric template <class ItTy, class FuncTy> 2310b57cec5SDimitry Andric inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) { 2320b57cec5SDimitry Andric return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F)); 2330b57cec5SDimitry Andric } 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric template <class ContainerTy, class FuncTy> 2360b57cec5SDimitry Andric auto map_range(ContainerTy &&C, FuncTy F) 2370b57cec5SDimitry Andric -> decltype(make_range(map_iterator(C.begin(), F), 2380b57cec5SDimitry Andric map_iterator(C.end(), F))) { 2390b57cec5SDimitry Andric return make_range(map_iterator(C.begin(), F), map_iterator(C.end(), F)); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric 2420b57cec5SDimitry Andric /// Helper to determine if type T has a member called rbegin(). 2430b57cec5SDimitry Andric template <typename Ty> class has_rbegin_impl { 2440b57cec5SDimitry Andric using yes = char[1]; 2450b57cec5SDimitry Andric using no = char[2]; 2460b57cec5SDimitry Andric 2470b57cec5SDimitry Andric template <typename Inner> 2480b57cec5SDimitry Andric static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr); 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric template <typename> 2510b57cec5SDimitry Andric static no& test(...); 2520b57cec5SDimitry Andric 2530b57cec5SDimitry Andric public: 2540b57cec5SDimitry Andric static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); 2550b57cec5SDimitry Andric }; 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric /// Metafunction to determine if T& or T has a member called rbegin(). 2580b57cec5SDimitry Andric template <typename Ty> 2590b57cec5SDimitry Andric struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> { 2600b57cec5SDimitry Andric }; 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric // Returns an iterator_range over the given container which iterates in reverse. 2630b57cec5SDimitry Andric // Note that the container must have rbegin()/rend() methods for this to work. 2640b57cec5SDimitry Andric template <typename ContainerTy> 2650b57cec5SDimitry Andric auto reverse(ContainerTy &&C, 2660b57cec5SDimitry Andric typename std::enable_if<has_rbegin<ContainerTy>::value>::type * = 2670b57cec5SDimitry Andric nullptr) -> decltype(make_range(C.rbegin(), C.rend())) { 2680b57cec5SDimitry Andric return make_range(C.rbegin(), C.rend()); 2690b57cec5SDimitry Andric } 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric // Returns a std::reverse_iterator wrapped around the given iterator. 2720b57cec5SDimitry Andric template <typename IteratorTy> 2730b57cec5SDimitry Andric std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) { 2740b57cec5SDimitry Andric return std::reverse_iterator<IteratorTy>(It); 2750b57cec5SDimitry Andric } 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric // Returns an iterator_range over the given container which iterates in reverse. 2780b57cec5SDimitry Andric // Note that the container must have begin()/end() methods which return 2790b57cec5SDimitry Andric // bidirectional iterators for this to work. 2800b57cec5SDimitry Andric template <typename ContainerTy> 2810b57cec5SDimitry Andric auto reverse( 2820b57cec5SDimitry Andric ContainerTy &&C, 2830b57cec5SDimitry Andric typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr) 2840b57cec5SDimitry Andric -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)), 2850b57cec5SDimitry Andric llvm::make_reverse_iterator(std::begin(C)))) { 2860b57cec5SDimitry Andric return make_range(llvm::make_reverse_iterator(std::end(C)), 2870b57cec5SDimitry Andric llvm::make_reverse_iterator(std::begin(C))); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric /// An iterator adaptor that filters the elements of given inner iterators. 2910b57cec5SDimitry Andric /// 2920b57cec5SDimitry Andric /// The predicate parameter should be a callable object that accepts the wrapped 2930b57cec5SDimitry Andric /// iterator's reference type and returns a bool. When incrementing or 2940b57cec5SDimitry Andric /// decrementing the iterator, it will call the predicate on each element and 2950b57cec5SDimitry Andric /// skip any where it returns false. 2960b57cec5SDimitry Andric /// 2970b57cec5SDimitry Andric /// \code 2980b57cec5SDimitry Andric /// int A[] = { 1, 2, 3, 4 }; 2990b57cec5SDimitry Andric /// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; }); 3000b57cec5SDimitry Andric /// // R contains { 1, 3 }. 3010b57cec5SDimitry Andric /// \endcode 3020b57cec5SDimitry Andric /// 3030b57cec5SDimitry Andric /// Note: filter_iterator_base implements support for forward iteration. 3040b57cec5SDimitry Andric /// filter_iterator_impl exists to provide support for bidirectional iteration, 3050b57cec5SDimitry Andric /// conditional on whether the wrapped iterator supports it. 3060b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT, typename IterTag> 3070b57cec5SDimitry Andric class filter_iterator_base 3080b57cec5SDimitry Andric : public iterator_adaptor_base< 3090b57cec5SDimitry Andric filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>, 3100b57cec5SDimitry Andric WrappedIteratorT, 3110b57cec5SDimitry Andric typename std::common_type< 3120b57cec5SDimitry Andric IterTag, typename std::iterator_traits< 3130b57cec5SDimitry Andric WrappedIteratorT>::iterator_category>::type> { 3140b57cec5SDimitry Andric using BaseT = iterator_adaptor_base< 3150b57cec5SDimitry Andric filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>, 3160b57cec5SDimitry Andric WrappedIteratorT, 3170b57cec5SDimitry Andric typename std::common_type< 3180b57cec5SDimitry Andric IterTag, typename std::iterator_traits< 3190b57cec5SDimitry Andric WrappedIteratorT>::iterator_category>::type>; 3200b57cec5SDimitry Andric 3210b57cec5SDimitry Andric protected: 3220b57cec5SDimitry Andric WrappedIteratorT End; 3230b57cec5SDimitry Andric PredicateT Pred; 3240b57cec5SDimitry Andric 3250b57cec5SDimitry Andric void findNextValid() { 3260b57cec5SDimitry Andric while (this->I != End && !Pred(*this->I)) 3270b57cec5SDimitry Andric BaseT::operator++(); 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric // Construct the iterator. The begin iterator needs to know where the end 3310b57cec5SDimitry Andric // is, so that it can properly stop when it gets there. The end iterator only 3320b57cec5SDimitry Andric // needs the predicate to support bidirectional iteration. 3330b57cec5SDimitry Andric filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End, 3340b57cec5SDimitry Andric PredicateT Pred) 3350b57cec5SDimitry Andric : BaseT(Begin), End(End), Pred(Pred) { 3360b57cec5SDimitry Andric findNextValid(); 3370b57cec5SDimitry Andric } 3380b57cec5SDimitry Andric 3390b57cec5SDimitry Andric public: 3400b57cec5SDimitry Andric using BaseT::operator++; 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric filter_iterator_base &operator++() { 3430b57cec5SDimitry Andric BaseT::operator++(); 3440b57cec5SDimitry Andric findNextValid(); 3450b57cec5SDimitry Andric return *this; 3460b57cec5SDimitry Andric } 3470b57cec5SDimitry Andric }; 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric /// Specialization of filter_iterator_base for forward iteration only. 3500b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT, 3510b57cec5SDimitry Andric typename IterTag = std::forward_iterator_tag> 3520b57cec5SDimitry Andric class filter_iterator_impl 3530b57cec5SDimitry Andric : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> { 3540b57cec5SDimitry Andric using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>; 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric public: 3570b57cec5SDimitry Andric filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, 3580b57cec5SDimitry Andric PredicateT Pred) 3590b57cec5SDimitry Andric : BaseT(Begin, End, Pred) {} 3600b57cec5SDimitry Andric }; 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric /// Specialization of filter_iterator_base for bidirectional iteration. 3630b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT> 3640b57cec5SDimitry Andric class filter_iterator_impl<WrappedIteratorT, PredicateT, 3650b57cec5SDimitry Andric std::bidirectional_iterator_tag> 3660b57cec5SDimitry Andric : public filter_iterator_base<WrappedIteratorT, PredicateT, 3670b57cec5SDimitry Andric std::bidirectional_iterator_tag> { 3680b57cec5SDimitry Andric using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, 3690b57cec5SDimitry Andric std::bidirectional_iterator_tag>; 3700b57cec5SDimitry Andric void findPrevValid() { 3710b57cec5SDimitry Andric while (!this->Pred(*this->I)) 3720b57cec5SDimitry Andric BaseT::operator--(); 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric 3750b57cec5SDimitry Andric public: 3760b57cec5SDimitry Andric using BaseT::operator--; 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, 3790b57cec5SDimitry Andric PredicateT Pred) 3800b57cec5SDimitry Andric : BaseT(Begin, End, Pred) {} 3810b57cec5SDimitry Andric 3820b57cec5SDimitry Andric filter_iterator_impl &operator--() { 3830b57cec5SDimitry Andric BaseT::operator--(); 3840b57cec5SDimitry Andric findPrevValid(); 3850b57cec5SDimitry Andric return *this; 3860b57cec5SDimitry Andric } 3870b57cec5SDimitry Andric }; 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric namespace detail { 3900b57cec5SDimitry Andric 3910b57cec5SDimitry Andric template <bool is_bidirectional> struct fwd_or_bidi_tag_impl { 3920b57cec5SDimitry Andric using type = std::forward_iterator_tag; 3930b57cec5SDimitry Andric }; 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric template <> struct fwd_or_bidi_tag_impl<true> { 3960b57cec5SDimitry Andric using type = std::bidirectional_iterator_tag; 3970b57cec5SDimitry Andric }; 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric /// Helper which sets its type member to forward_iterator_tag if the category 4000b57cec5SDimitry Andric /// of \p IterT does not derive from bidirectional_iterator_tag, and to 4010b57cec5SDimitry Andric /// bidirectional_iterator_tag otherwise. 4020b57cec5SDimitry Andric template <typename IterT> struct fwd_or_bidi_tag { 4030b57cec5SDimitry Andric using type = typename fwd_or_bidi_tag_impl<std::is_base_of< 4040b57cec5SDimitry Andric std::bidirectional_iterator_tag, 4050b57cec5SDimitry Andric typename std::iterator_traits<IterT>::iterator_category>::value>::type; 4060b57cec5SDimitry Andric }; 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric } // namespace detail 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric /// Defines filter_iterator to a suitable specialization of 4110b57cec5SDimitry Andric /// filter_iterator_impl, based on the underlying iterator's category. 4120b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT> 4130b57cec5SDimitry Andric using filter_iterator = filter_iterator_impl< 4140b57cec5SDimitry Andric WrappedIteratorT, PredicateT, 4150b57cec5SDimitry Andric typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>; 4160b57cec5SDimitry Andric 4170b57cec5SDimitry Andric /// Convenience function that takes a range of elements and a predicate, 4180b57cec5SDimitry Andric /// and return a new filter_iterator range. 4190b57cec5SDimitry Andric /// 4200b57cec5SDimitry Andric /// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the 4210b57cec5SDimitry Andric /// lifetime of that temporary is not kept by the returned range object, and the 4220b57cec5SDimitry Andric /// temporary is going to be dropped on the floor after the make_iterator_range 4230b57cec5SDimitry Andric /// full expression that contains this function call. 4240b57cec5SDimitry Andric template <typename RangeT, typename PredicateT> 4250b57cec5SDimitry Andric iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>> 4260b57cec5SDimitry Andric make_filter_range(RangeT &&Range, PredicateT Pred) { 4270b57cec5SDimitry Andric using FilterIteratorT = 4280b57cec5SDimitry Andric filter_iterator<detail::IterOfRange<RangeT>, PredicateT>; 4290b57cec5SDimitry Andric return make_range( 4300b57cec5SDimitry Andric FilterIteratorT(std::begin(std::forward<RangeT>(Range)), 4310b57cec5SDimitry Andric std::end(std::forward<RangeT>(Range)), Pred), 4320b57cec5SDimitry Andric FilterIteratorT(std::end(std::forward<RangeT>(Range)), 4330b57cec5SDimitry Andric std::end(std::forward<RangeT>(Range)), Pred)); 4340b57cec5SDimitry Andric } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric /// A pseudo-iterator adaptor that is designed to implement "early increment" 4370b57cec5SDimitry Andric /// style loops. 4380b57cec5SDimitry Andric /// 4390b57cec5SDimitry Andric /// This is *not a normal iterator* and should almost never be used directly. It 4400b57cec5SDimitry Andric /// is intended primarily to be used with range based for loops and some range 4410b57cec5SDimitry Andric /// algorithms. 4420b57cec5SDimitry Andric /// 4430b57cec5SDimitry Andric /// The iterator isn't quite an `OutputIterator` or an `InputIterator` but 4440b57cec5SDimitry Andric /// somewhere between them. The constraints of these iterators are: 4450b57cec5SDimitry Andric /// 4460b57cec5SDimitry Andric /// - On construction or after being incremented, it is comparable and 4470b57cec5SDimitry Andric /// dereferencable. It is *not* incrementable. 4480b57cec5SDimitry Andric /// - After being dereferenced, it is neither comparable nor dereferencable, it 4490b57cec5SDimitry Andric /// is only incrementable. 4500b57cec5SDimitry Andric /// 4510b57cec5SDimitry Andric /// This means you can only dereference the iterator once, and you can only 4520b57cec5SDimitry Andric /// increment it once between dereferences. 4530b57cec5SDimitry Andric template <typename WrappedIteratorT> 4540b57cec5SDimitry Andric class early_inc_iterator_impl 4550b57cec5SDimitry Andric : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>, 4560b57cec5SDimitry Andric WrappedIteratorT, std::input_iterator_tag> { 4570b57cec5SDimitry Andric using BaseT = 4580b57cec5SDimitry Andric iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>, 4590b57cec5SDimitry Andric WrappedIteratorT, std::input_iterator_tag>; 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer; 4620b57cec5SDimitry Andric 4630b57cec5SDimitry Andric protected: 4640b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS 4650b57cec5SDimitry Andric bool IsEarlyIncremented = false; 4660b57cec5SDimitry Andric #endif 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric public: 4690b57cec5SDimitry Andric early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {} 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric using BaseT::operator*; 4720b57cec5SDimitry Andric typename BaseT::reference operator*() { 4730b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS 4740b57cec5SDimitry Andric assert(!IsEarlyIncremented && "Cannot dereference twice!"); 4750b57cec5SDimitry Andric IsEarlyIncremented = true; 4760b57cec5SDimitry Andric #endif 4770b57cec5SDimitry Andric return *(this->I)++; 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric using BaseT::operator++; 4810b57cec5SDimitry Andric early_inc_iterator_impl &operator++() { 4820b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS 4830b57cec5SDimitry Andric assert(IsEarlyIncremented && "Cannot increment before dereferencing!"); 4840b57cec5SDimitry Andric IsEarlyIncremented = false; 4850b57cec5SDimitry Andric #endif 4860b57cec5SDimitry Andric return *this; 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric using BaseT::operator==; 4900b57cec5SDimitry Andric bool operator==(const early_inc_iterator_impl &RHS) const { 4910b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS 4920b57cec5SDimitry Andric assert(!IsEarlyIncremented && "Cannot compare after dereferencing!"); 4930b57cec5SDimitry Andric #endif 4940b57cec5SDimitry Andric return BaseT::operator==(RHS); 4950b57cec5SDimitry Andric } 4960b57cec5SDimitry Andric }; 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric /// Make a range that does early increment to allow mutation of the underlying 4990b57cec5SDimitry Andric /// range without disrupting iteration. 5000b57cec5SDimitry Andric /// 5010b57cec5SDimitry Andric /// The underlying iterator will be incremented immediately after it is 5020b57cec5SDimitry Andric /// dereferenced, allowing deletion of the current node or insertion of nodes to 5030b57cec5SDimitry Andric /// not disrupt iteration provided they do not invalidate the *next* iterator -- 5040b57cec5SDimitry Andric /// the current iterator can be invalidated. 5050b57cec5SDimitry Andric /// 5060b57cec5SDimitry Andric /// This requires a very exact pattern of use that is only really suitable to 5070b57cec5SDimitry Andric /// range based for loops and other range algorithms that explicitly guarantee 5080b57cec5SDimitry Andric /// to dereference exactly once each element, and to increment exactly once each 5090b57cec5SDimitry Andric /// element. 5100b57cec5SDimitry Andric template <typename RangeT> 5110b57cec5SDimitry Andric iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>> 5120b57cec5SDimitry Andric make_early_inc_range(RangeT &&Range) { 5130b57cec5SDimitry Andric using EarlyIncIteratorT = 5140b57cec5SDimitry Andric early_inc_iterator_impl<detail::IterOfRange<RangeT>>; 5150b57cec5SDimitry Andric return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))), 5160b57cec5SDimitry Andric EarlyIncIteratorT(std::end(std::forward<RangeT>(Range)))); 5170b57cec5SDimitry Andric } 5180b57cec5SDimitry Andric 5190b57cec5SDimitry Andric // forward declarations required by zip_shortest/zip_first/zip_longest 5200b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 5210b57cec5SDimitry Andric bool all_of(R &&range, UnaryPredicate P); 5220b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 5230b57cec5SDimitry Andric bool any_of(R &&range, UnaryPredicate P); 5240b57cec5SDimitry Andric 5250b57cec5SDimitry Andric namespace detail { 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric using std::declval; 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric // We have to alias this since inlining the actual type at the usage site 5300b57cec5SDimitry Andric // in the parameter list of iterator_facade_base<> below ICEs MSVC 2017. 5310b57cec5SDimitry Andric template<typename... Iters> struct ZipTupleType { 5320b57cec5SDimitry Andric using type = std::tuple<decltype(*declval<Iters>())...>; 5330b57cec5SDimitry Andric }; 5340b57cec5SDimitry Andric 5350b57cec5SDimitry Andric template <typename ZipType, typename... Iters> 5360b57cec5SDimitry Andric using zip_traits = iterator_facade_base< 5370b57cec5SDimitry Andric ZipType, typename std::common_type<std::bidirectional_iterator_tag, 5380b57cec5SDimitry Andric typename std::iterator_traits< 5390b57cec5SDimitry Andric Iters>::iterator_category...>::type, 5400b57cec5SDimitry Andric // ^ TODO: Implement random access methods. 5410b57cec5SDimitry Andric typename ZipTupleType<Iters...>::type, 5420b57cec5SDimitry Andric typename std::iterator_traits<typename std::tuple_element< 5430b57cec5SDimitry Andric 0, std::tuple<Iters...>>::type>::difference_type, 5440b57cec5SDimitry Andric // ^ FIXME: This follows boost::make_zip_iterator's assumption that all 5450b57cec5SDimitry Andric // inner iterators have the same difference_type. It would fail if, for 5460b57cec5SDimitry Andric // instance, the second field's difference_type were non-numeric while the 5470b57cec5SDimitry Andric // first is. 5480b57cec5SDimitry Andric typename ZipTupleType<Iters...>::type *, 5490b57cec5SDimitry Andric typename ZipTupleType<Iters...>::type>; 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric template <typename ZipType, typename... Iters> 5520b57cec5SDimitry Andric struct zip_common : public zip_traits<ZipType, Iters...> { 5530b57cec5SDimitry Andric using Base = zip_traits<ZipType, Iters...>; 5540b57cec5SDimitry Andric using value_type = typename Base::value_type; 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric std::tuple<Iters...> iterators; 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric protected: 5598bcb0991SDimitry Andric template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const { 5600b57cec5SDimitry Andric return value_type(*std::get<Ns>(iterators)...); 5610b57cec5SDimitry Andric } 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric template <size_t... Ns> 5648bcb0991SDimitry Andric decltype(iterators) tup_inc(std::index_sequence<Ns...>) const { 5650b57cec5SDimitry Andric return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...); 5660b57cec5SDimitry Andric } 5670b57cec5SDimitry Andric 5680b57cec5SDimitry Andric template <size_t... Ns> 5698bcb0991SDimitry Andric decltype(iterators) tup_dec(std::index_sequence<Ns...>) const { 5700b57cec5SDimitry Andric return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...); 5710b57cec5SDimitry Andric } 5720b57cec5SDimitry Andric 5730b57cec5SDimitry Andric public: 5740b57cec5SDimitry Andric zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {} 5750b57cec5SDimitry Andric 5768bcb0991SDimitry Andric value_type operator*() { return deref(std::index_sequence_for<Iters...>{}); } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric const value_type operator*() const { 5798bcb0991SDimitry Andric return deref(std::index_sequence_for<Iters...>{}); 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric ZipType &operator++() { 5838bcb0991SDimitry Andric iterators = tup_inc(std::index_sequence_for<Iters...>{}); 5840b57cec5SDimitry Andric return *reinterpret_cast<ZipType *>(this); 5850b57cec5SDimitry Andric } 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric ZipType &operator--() { 5880b57cec5SDimitry Andric static_assert(Base::IsBidirectional, 5890b57cec5SDimitry Andric "All inner iterators must be at least bidirectional."); 5908bcb0991SDimitry Andric iterators = tup_dec(std::index_sequence_for<Iters...>{}); 5910b57cec5SDimitry Andric return *reinterpret_cast<ZipType *>(this); 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric }; 5940b57cec5SDimitry Andric 5950b57cec5SDimitry Andric template <typename... Iters> 5960b57cec5SDimitry Andric struct zip_first : public zip_common<zip_first<Iters...>, Iters...> { 5970b57cec5SDimitry Andric using Base = zip_common<zip_first<Iters...>, Iters...>; 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric bool operator==(const zip_first<Iters...> &other) const { 6000b57cec5SDimitry Andric return std::get<0>(this->iterators) == std::get<0>(other.iterators); 6010b57cec5SDimitry Andric } 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} 6040b57cec5SDimitry Andric }; 6050b57cec5SDimitry Andric 6060b57cec5SDimitry Andric template <typename... Iters> 6070b57cec5SDimitry Andric class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> { 6080b57cec5SDimitry Andric template <size_t... Ns> 6098bcb0991SDimitry Andric bool test(const zip_shortest<Iters...> &other, 6108bcb0991SDimitry Andric std::index_sequence<Ns...>) const { 6110b57cec5SDimitry Andric return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) != 6120b57cec5SDimitry Andric std::get<Ns>(other.iterators)...}, 6130b57cec5SDimitry Andric identity<bool>{}); 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric public: 6170b57cec5SDimitry Andric using Base = zip_common<zip_shortest<Iters...>, Iters...>; 6180b57cec5SDimitry Andric 6190b57cec5SDimitry Andric zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric bool operator==(const zip_shortest<Iters...> &other) const { 6228bcb0991SDimitry Andric return !test(other, std::index_sequence_for<Iters...>{}); 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric }; 6250b57cec5SDimitry Andric 6260b57cec5SDimitry Andric template <template <typename...> class ItType, typename... Args> class zippy { 6270b57cec5SDimitry Andric public: 6280b57cec5SDimitry Andric using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>; 6290b57cec5SDimitry Andric using iterator_category = typename iterator::iterator_category; 6300b57cec5SDimitry Andric using value_type = typename iterator::value_type; 6310b57cec5SDimitry Andric using difference_type = typename iterator::difference_type; 6320b57cec5SDimitry Andric using pointer = typename iterator::pointer; 6330b57cec5SDimitry Andric using reference = typename iterator::reference; 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric private: 6360b57cec5SDimitry Andric std::tuple<Args...> ts; 6370b57cec5SDimitry Andric 6388bcb0991SDimitry Andric template <size_t... Ns> 6398bcb0991SDimitry Andric iterator begin_impl(std::index_sequence<Ns...>) const { 6400b57cec5SDimitry Andric return iterator(std::begin(std::get<Ns>(ts))...); 6410b57cec5SDimitry Andric } 6428bcb0991SDimitry Andric template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const { 6430b57cec5SDimitry Andric return iterator(std::end(std::get<Ns>(ts))...); 6440b57cec5SDimitry Andric } 6450b57cec5SDimitry Andric 6460b57cec5SDimitry Andric public: 6470b57cec5SDimitry Andric zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} 6480b57cec5SDimitry Andric 6498bcb0991SDimitry Andric iterator begin() const { 6508bcb0991SDimitry Andric return begin_impl(std::index_sequence_for<Args...>{}); 6518bcb0991SDimitry Andric } 6528bcb0991SDimitry Andric iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); } 6530b57cec5SDimitry Andric }; 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric } // end namespace detail 6560b57cec5SDimitry Andric 6570b57cec5SDimitry Andric /// zip iterator for two or more iteratable types. 6580b57cec5SDimitry Andric template <typename T, typename U, typename... Args> 6590b57cec5SDimitry Andric detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u, 6600b57cec5SDimitry Andric Args &&... args) { 6610b57cec5SDimitry Andric return detail::zippy<detail::zip_shortest, T, U, Args...>( 6620b57cec5SDimitry Andric std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); 6630b57cec5SDimitry Andric } 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric /// zip iterator that, for the sake of efficiency, assumes the first iteratee to 6660b57cec5SDimitry Andric /// be the shortest. 6670b57cec5SDimitry Andric template <typename T, typename U, typename... Args> 6680b57cec5SDimitry Andric detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u, 6690b57cec5SDimitry Andric Args &&... args) { 6700b57cec5SDimitry Andric return detail::zippy<detail::zip_first, T, U, Args...>( 6710b57cec5SDimitry Andric std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); 6720b57cec5SDimitry Andric } 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric namespace detail { 6750b57cec5SDimitry Andric template <typename Iter> 6760b57cec5SDimitry Andric static Iter next_or_end(const Iter &I, const Iter &End) { 6770b57cec5SDimitry Andric if (I == End) 6780b57cec5SDimitry Andric return End; 6790b57cec5SDimitry Andric return std::next(I); 6800b57cec5SDimitry Andric } 6810b57cec5SDimitry Andric 6820b57cec5SDimitry Andric template <typename Iter> 6830b57cec5SDimitry Andric static auto deref_or_none(const Iter &I, const Iter &End) 6840b57cec5SDimitry Andric -> llvm::Optional<typename std::remove_const< 6850b57cec5SDimitry Andric typename std::remove_reference<decltype(*I)>::type>::type> { 6860b57cec5SDimitry Andric if (I == End) 6870b57cec5SDimitry Andric return None; 6880b57cec5SDimitry Andric return *I; 6890b57cec5SDimitry Andric } 6900b57cec5SDimitry Andric 6910b57cec5SDimitry Andric template <typename Iter> struct ZipLongestItemType { 6920b57cec5SDimitry Andric using type = 6930b57cec5SDimitry Andric llvm::Optional<typename std::remove_const<typename std::remove_reference< 6940b57cec5SDimitry Andric decltype(*std::declval<Iter>())>::type>::type>; 6950b57cec5SDimitry Andric }; 6960b57cec5SDimitry Andric 6970b57cec5SDimitry Andric template <typename... Iters> struct ZipLongestTupleType { 6980b57cec5SDimitry Andric using type = std::tuple<typename ZipLongestItemType<Iters>::type...>; 6990b57cec5SDimitry Andric }; 7000b57cec5SDimitry Andric 7010b57cec5SDimitry Andric template <typename... Iters> 7020b57cec5SDimitry Andric class zip_longest_iterator 7030b57cec5SDimitry Andric : public iterator_facade_base< 7040b57cec5SDimitry Andric zip_longest_iterator<Iters...>, 7050b57cec5SDimitry Andric typename std::common_type< 7060b57cec5SDimitry Andric std::forward_iterator_tag, 7070b57cec5SDimitry Andric typename std::iterator_traits<Iters>::iterator_category...>::type, 7080b57cec5SDimitry Andric typename ZipLongestTupleType<Iters...>::type, 7090b57cec5SDimitry Andric typename std::iterator_traits<typename std::tuple_element< 7100b57cec5SDimitry Andric 0, std::tuple<Iters...>>::type>::difference_type, 7110b57cec5SDimitry Andric typename ZipLongestTupleType<Iters...>::type *, 7120b57cec5SDimitry Andric typename ZipLongestTupleType<Iters...>::type> { 7130b57cec5SDimitry Andric public: 7140b57cec5SDimitry Andric using value_type = typename ZipLongestTupleType<Iters...>::type; 7150b57cec5SDimitry Andric 7160b57cec5SDimitry Andric private: 7170b57cec5SDimitry Andric std::tuple<Iters...> iterators; 7180b57cec5SDimitry Andric std::tuple<Iters...> end_iterators; 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric template <size_t... Ns> 7210b57cec5SDimitry Andric bool test(const zip_longest_iterator<Iters...> &other, 7228bcb0991SDimitry Andric std::index_sequence<Ns...>) const { 7230b57cec5SDimitry Andric return llvm::any_of( 7240b57cec5SDimitry Andric std::initializer_list<bool>{std::get<Ns>(this->iterators) != 7250b57cec5SDimitry Andric std::get<Ns>(other.iterators)...}, 7260b57cec5SDimitry Andric identity<bool>{}); 7270b57cec5SDimitry Andric } 7280b57cec5SDimitry Andric 7298bcb0991SDimitry Andric template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const { 7300b57cec5SDimitry Andric return value_type( 7310b57cec5SDimitry Andric deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...); 7320b57cec5SDimitry Andric } 7330b57cec5SDimitry Andric 7340b57cec5SDimitry Andric template <size_t... Ns> 7358bcb0991SDimitry Andric decltype(iterators) tup_inc(std::index_sequence<Ns...>) const { 7360b57cec5SDimitry Andric return std::tuple<Iters...>( 7370b57cec5SDimitry Andric next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...); 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric 7400b57cec5SDimitry Andric public: 7410b57cec5SDimitry Andric zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts) 7420b57cec5SDimitry Andric : iterators(std::forward<Iters>(ts.first)...), 7430b57cec5SDimitry Andric end_iterators(std::forward<Iters>(ts.second)...) {} 7440b57cec5SDimitry Andric 7458bcb0991SDimitry Andric value_type operator*() { return deref(std::index_sequence_for<Iters...>{}); } 7460b57cec5SDimitry Andric 7478bcb0991SDimitry Andric value_type operator*() const { 7488bcb0991SDimitry Andric return deref(std::index_sequence_for<Iters...>{}); 7498bcb0991SDimitry Andric } 7500b57cec5SDimitry Andric 7510b57cec5SDimitry Andric zip_longest_iterator<Iters...> &operator++() { 7528bcb0991SDimitry Andric iterators = tup_inc(std::index_sequence_for<Iters...>{}); 7530b57cec5SDimitry Andric return *this; 7540b57cec5SDimitry Andric } 7550b57cec5SDimitry Andric 7560b57cec5SDimitry Andric bool operator==(const zip_longest_iterator<Iters...> &other) const { 7578bcb0991SDimitry Andric return !test(other, std::index_sequence_for<Iters...>{}); 7580b57cec5SDimitry Andric } 7590b57cec5SDimitry Andric }; 7600b57cec5SDimitry Andric 7610b57cec5SDimitry Andric template <typename... Args> class zip_longest_range { 7620b57cec5SDimitry Andric public: 7630b57cec5SDimitry Andric using iterator = 7640b57cec5SDimitry Andric zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>; 7650b57cec5SDimitry Andric using iterator_category = typename iterator::iterator_category; 7660b57cec5SDimitry Andric using value_type = typename iterator::value_type; 7670b57cec5SDimitry Andric using difference_type = typename iterator::difference_type; 7680b57cec5SDimitry Andric using pointer = typename iterator::pointer; 7690b57cec5SDimitry Andric using reference = typename iterator::reference; 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric private: 7720b57cec5SDimitry Andric std::tuple<Args...> ts; 7730b57cec5SDimitry Andric 7748bcb0991SDimitry Andric template <size_t... Ns> 7758bcb0991SDimitry Andric iterator begin_impl(std::index_sequence<Ns...>) const { 7760b57cec5SDimitry Andric return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)), 7770b57cec5SDimitry Andric adl_end(std::get<Ns>(ts)))...); 7780b57cec5SDimitry Andric } 7790b57cec5SDimitry Andric 7808bcb0991SDimitry Andric template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const { 7810b57cec5SDimitry Andric return iterator(std::make_pair(adl_end(std::get<Ns>(ts)), 7820b57cec5SDimitry Andric adl_end(std::get<Ns>(ts)))...); 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric public: 7860b57cec5SDimitry Andric zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} 7870b57cec5SDimitry Andric 7888bcb0991SDimitry Andric iterator begin() const { 7898bcb0991SDimitry Andric return begin_impl(std::index_sequence_for<Args...>{}); 7908bcb0991SDimitry Andric } 7918bcb0991SDimitry Andric iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); } 7920b57cec5SDimitry Andric }; 7930b57cec5SDimitry Andric } // namespace detail 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric /// Iterate over two or more iterators at the same time. Iteration continues 7960b57cec5SDimitry Andric /// until all iterators reach the end. The llvm::Optional only contains a value 7970b57cec5SDimitry Andric /// if the iterator has not reached the end. 7980b57cec5SDimitry Andric template <typename T, typename U, typename... Args> 7990b57cec5SDimitry Andric detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u, 8000b57cec5SDimitry Andric Args &&... args) { 8010b57cec5SDimitry Andric return detail::zip_longest_range<T, U, Args...>( 8020b57cec5SDimitry Andric std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); 8030b57cec5SDimitry Andric } 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric /// Iterator wrapper that concatenates sequences together. 8060b57cec5SDimitry Andric /// 8070b57cec5SDimitry Andric /// This can concatenate different iterators, even with different types, into 8080b57cec5SDimitry Andric /// a single iterator provided the value types of all the concatenated 8090b57cec5SDimitry Andric /// iterators expose `reference` and `pointer` types that can be converted to 8100b57cec5SDimitry Andric /// `ValueT &` and `ValueT *` respectively. It doesn't support more 8110b57cec5SDimitry Andric /// interesting/customized pointer or reference types. 8120b57cec5SDimitry Andric /// 8130b57cec5SDimitry Andric /// Currently this only supports forward or higher iterator categories as 8140b57cec5SDimitry Andric /// inputs and always exposes a forward iterator interface. 8150b57cec5SDimitry Andric template <typename ValueT, typename... IterTs> 8160b57cec5SDimitry Andric class concat_iterator 8170b57cec5SDimitry Andric : public iterator_facade_base<concat_iterator<ValueT, IterTs...>, 8180b57cec5SDimitry Andric std::forward_iterator_tag, ValueT> { 8190b57cec5SDimitry Andric using BaseT = typename concat_iterator::iterator_facade_base; 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andric /// We store both the current and end iterators for each concatenated 8220b57cec5SDimitry Andric /// sequence in a tuple of pairs. 8230b57cec5SDimitry Andric /// 8240b57cec5SDimitry Andric /// Note that something like iterator_range seems nice at first here, but the 8250b57cec5SDimitry Andric /// range properties are of little benefit and end up getting in the way 8260b57cec5SDimitry Andric /// because we need to do mutation on the current iterators. 8270b57cec5SDimitry Andric std::tuple<IterTs...> Begins; 8280b57cec5SDimitry Andric std::tuple<IterTs...> Ends; 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric /// Attempts to increment a specific iterator. 8310b57cec5SDimitry Andric /// 8320b57cec5SDimitry Andric /// Returns true if it was able to increment the iterator. Returns false if 8330b57cec5SDimitry Andric /// the iterator is already at the end iterator. 8340b57cec5SDimitry Andric template <size_t Index> bool incrementHelper() { 8350b57cec5SDimitry Andric auto &Begin = std::get<Index>(Begins); 8360b57cec5SDimitry Andric auto &End = std::get<Index>(Ends); 8370b57cec5SDimitry Andric if (Begin == End) 8380b57cec5SDimitry Andric return false; 8390b57cec5SDimitry Andric 8400b57cec5SDimitry Andric ++Begin; 8410b57cec5SDimitry Andric return true; 8420b57cec5SDimitry Andric } 8430b57cec5SDimitry Andric 8440b57cec5SDimitry Andric /// Increments the first non-end iterator. 8450b57cec5SDimitry Andric /// 8460b57cec5SDimitry Andric /// It is an error to call this with all iterators at the end. 8478bcb0991SDimitry Andric template <size_t... Ns> void increment(std::index_sequence<Ns...>) { 8480b57cec5SDimitry Andric // Build a sequence of functions to increment each iterator if possible. 8490b57cec5SDimitry Andric bool (concat_iterator::*IncrementHelperFns[])() = { 8500b57cec5SDimitry Andric &concat_iterator::incrementHelper<Ns>...}; 8510b57cec5SDimitry Andric 8520b57cec5SDimitry Andric // Loop over them, and stop as soon as we succeed at incrementing one. 8530b57cec5SDimitry Andric for (auto &IncrementHelperFn : IncrementHelperFns) 8540b57cec5SDimitry Andric if ((this->*IncrementHelperFn)()) 8550b57cec5SDimitry Andric return; 8560b57cec5SDimitry Andric 8570b57cec5SDimitry Andric llvm_unreachable("Attempted to increment an end concat iterator!"); 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric /// Returns null if the specified iterator is at the end. Otherwise, 8610b57cec5SDimitry Andric /// dereferences the iterator and returns the address of the resulting 8620b57cec5SDimitry Andric /// reference. 8630b57cec5SDimitry Andric template <size_t Index> ValueT *getHelper() const { 8640b57cec5SDimitry Andric auto &Begin = std::get<Index>(Begins); 8650b57cec5SDimitry Andric auto &End = std::get<Index>(Ends); 8660b57cec5SDimitry Andric if (Begin == End) 8670b57cec5SDimitry Andric return nullptr; 8680b57cec5SDimitry Andric 8690b57cec5SDimitry Andric return &*Begin; 8700b57cec5SDimitry Andric } 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric /// Finds the first non-end iterator, dereferences, and returns the resulting 8730b57cec5SDimitry Andric /// reference. 8740b57cec5SDimitry Andric /// 8750b57cec5SDimitry Andric /// It is an error to call this with all iterators at the end. 8768bcb0991SDimitry Andric template <size_t... Ns> ValueT &get(std::index_sequence<Ns...>) const { 8770b57cec5SDimitry Andric // Build a sequence of functions to get from iterator if possible. 8780b57cec5SDimitry Andric ValueT *(concat_iterator::*GetHelperFns[])() const = { 8790b57cec5SDimitry Andric &concat_iterator::getHelper<Ns>...}; 8800b57cec5SDimitry Andric 8810b57cec5SDimitry Andric // Loop over them, and return the first result we find. 8820b57cec5SDimitry Andric for (auto &GetHelperFn : GetHelperFns) 8830b57cec5SDimitry Andric if (ValueT *P = (this->*GetHelperFn)()) 8840b57cec5SDimitry Andric return *P; 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric llvm_unreachable("Attempted to get a pointer from an end concat iterator!"); 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric public: 8900b57cec5SDimitry Andric /// Constructs an iterator from a squence of ranges. 8910b57cec5SDimitry Andric /// 8920b57cec5SDimitry Andric /// We need the full range to know how to switch between each of the 8930b57cec5SDimitry Andric /// iterators. 8940b57cec5SDimitry Andric template <typename... RangeTs> 8950b57cec5SDimitry Andric explicit concat_iterator(RangeTs &&... Ranges) 8960b57cec5SDimitry Andric : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {} 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric using BaseT::operator++; 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric concat_iterator &operator++() { 9018bcb0991SDimitry Andric increment(std::index_sequence_for<IterTs...>()); 9020b57cec5SDimitry Andric return *this; 9030b57cec5SDimitry Andric } 9040b57cec5SDimitry Andric 9058bcb0991SDimitry Andric ValueT &operator*() const { 9068bcb0991SDimitry Andric return get(std::index_sequence_for<IterTs...>()); 9078bcb0991SDimitry Andric } 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric bool operator==(const concat_iterator &RHS) const { 9100b57cec5SDimitry Andric return Begins == RHS.Begins && Ends == RHS.Ends; 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric }; 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric namespace detail { 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric /// Helper to store a sequence of ranges being concatenated and access them. 9170b57cec5SDimitry Andric /// 9180b57cec5SDimitry Andric /// This is designed to facilitate providing actual storage when temporaries 9190b57cec5SDimitry Andric /// are passed into the constructor such that we can use it as part of range 9200b57cec5SDimitry Andric /// based for loops. 9210b57cec5SDimitry Andric template <typename ValueT, typename... RangeTs> class concat_range { 9220b57cec5SDimitry Andric public: 9230b57cec5SDimitry Andric using iterator = 9240b57cec5SDimitry Andric concat_iterator<ValueT, 9250b57cec5SDimitry Andric decltype(std::begin(std::declval<RangeTs &>()))...>; 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric private: 9280b57cec5SDimitry Andric std::tuple<RangeTs...> Ranges; 9290b57cec5SDimitry Andric 9308bcb0991SDimitry Andric template <size_t... Ns> iterator begin_impl(std::index_sequence<Ns...>) { 9310b57cec5SDimitry Andric return iterator(std::get<Ns>(Ranges)...); 9320b57cec5SDimitry Andric } 9338bcb0991SDimitry Andric template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) { 9340b57cec5SDimitry Andric return iterator(make_range(std::end(std::get<Ns>(Ranges)), 9350b57cec5SDimitry Andric std::end(std::get<Ns>(Ranges)))...); 9360b57cec5SDimitry Andric } 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric public: 9390b57cec5SDimitry Andric concat_range(RangeTs &&... Ranges) 9400b57cec5SDimitry Andric : Ranges(std::forward<RangeTs>(Ranges)...) {} 9410b57cec5SDimitry Andric 9428bcb0991SDimitry Andric iterator begin() { return begin_impl(std::index_sequence_for<RangeTs...>{}); } 9438bcb0991SDimitry Andric iterator end() { return end_impl(std::index_sequence_for<RangeTs...>{}); } 9440b57cec5SDimitry Andric }; 9450b57cec5SDimitry Andric 9460b57cec5SDimitry Andric } // end namespace detail 9470b57cec5SDimitry Andric 9480b57cec5SDimitry Andric /// Concatenated range across two or more ranges. 9490b57cec5SDimitry Andric /// 9500b57cec5SDimitry Andric /// The desired value type must be explicitly specified. 9510b57cec5SDimitry Andric template <typename ValueT, typename... RangeTs> 9520b57cec5SDimitry Andric detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) { 9530b57cec5SDimitry Andric static_assert(sizeof...(RangeTs) > 1, 9540b57cec5SDimitry Andric "Need more than one range to concatenate!"); 9550b57cec5SDimitry Andric return detail::concat_range<ValueT, RangeTs...>( 9560b57cec5SDimitry Andric std::forward<RangeTs>(Ranges)...); 9570b57cec5SDimitry Andric } 9580b57cec5SDimitry Andric 9590b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 9600b57cec5SDimitry Andric // Extra additions to <utility> 9610b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric /// Function object to check whether the first component of a std::pair 9640b57cec5SDimitry Andric /// compares less than the first component of another std::pair. 9650b57cec5SDimitry Andric struct less_first { 9660b57cec5SDimitry Andric template <typename T> bool operator()(const T &lhs, const T &rhs) const { 9670b57cec5SDimitry Andric return lhs.first < rhs.first; 9680b57cec5SDimitry Andric } 9690b57cec5SDimitry Andric }; 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric /// Function object to check whether the second component of a std::pair 9720b57cec5SDimitry Andric /// compares less than the second component of another std::pair. 9730b57cec5SDimitry Andric struct less_second { 9740b57cec5SDimitry Andric template <typename T> bool operator()(const T &lhs, const T &rhs) const { 9750b57cec5SDimitry Andric return lhs.second < rhs.second; 9760b57cec5SDimitry Andric } 9770b57cec5SDimitry Andric }; 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric /// \brief Function object to apply a binary function to the first component of 9800b57cec5SDimitry Andric /// a std::pair. 9810b57cec5SDimitry Andric template<typename FuncTy> 9820b57cec5SDimitry Andric struct on_first { 9830b57cec5SDimitry Andric FuncTy func; 9840b57cec5SDimitry Andric 9850b57cec5SDimitry Andric template <typename T> 9860b57cec5SDimitry Andric auto operator()(const T &lhs, const T &rhs) const 9870b57cec5SDimitry Andric -> decltype(func(lhs.first, rhs.first)) { 9880b57cec5SDimitry Andric return func(lhs.first, rhs.first); 9890b57cec5SDimitry Andric } 9900b57cec5SDimitry Andric }; 9910b57cec5SDimitry Andric 9920b57cec5SDimitry Andric /// Utility type to build an inheritance chain that makes it easy to rank 9930b57cec5SDimitry Andric /// overload candidates. 9940b57cec5SDimitry Andric template <int N> struct rank : rank<N - 1> {}; 9950b57cec5SDimitry Andric template <> struct rank<0> {}; 9960b57cec5SDimitry Andric 9970b57cec5SDimitry Andric /// traits class for checking whether type T is one of any of the given 9980b57cec5SDimitry Andric /// types in the variadic list. 9990b57cec5SDimitry Andric template <typename T, typename... Ts> struct is_one_of { 10000b57cec5SDimitry Andric static const bool value = false; 10010b57cec5SDimitry Andric }; 10020b57cec5SDimitry Andric 10030b57cec5SDimitry Andric template <typename T, typename U, typename... Ts> 10040b57cec5SDimitry Andric struct is_one_of<T, U, Ts...> { 10050b57cec5SDimitry Andric static const bool value = 10060b57cec5SDimitry Andric std::is_same<T, U>::value || is_one_of<T, Ts...>::value; 10070b57cec5SDimitry Andric }; 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andric /// traits class for checking whether type T is a base class for all 10100b57cec5SDimitry Andric /// the given types in the variadic list. 10110b57cec5SDimitry Andric template <typename T, typename... Ts> struct are_base_of { 10120b57cec5SDimitry Andric static const bool value = true; 10130b57cec5SDimitry Andric }; 10140b57cec5SDimitry Andric 10150b57cec5SDimitry Andric template <typename T, typename U, typename... Ts> 10160b57cec5SDimitry Andric struct are_base_of<T, U, Ts...> { 10170b57cec5SDimitry Andric static const bool value = 10180b57cec5SDimitry Andric std::is_base_of<T, U>::value && are_base_of<T, Ts...>::value; 10190b57cec5SDimitry Andric }; 10200b57cec5SDimitry Andric 10210b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 10220b57cec5SDimitry Andric // Extra additions for arrays 10230b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric /// Find the length of an array. 10260b57cec5SDimitry Andric template <class T, std::size_t N> 10270b57cec5SDimitry Andric constexpr inline size_t array_lengthof(T (&)[N]) { 10280b57cec5SDimitry Andric return N; 10290b57cec5SDimitry Andric } 10300b57cec5SDimitry Andric 10310b57cec5SDimitry Andric /// Adapt std::less<T> for array_pod_sort. 10320b57cec5SDimitry Andric template<typename T> 10330b57cec5SDimitry Andric inline int array_pod_sort_comparator(const void *P1, const void *P2) { 10340b57cec5SDimitry Andric if (std::less<T>()(*reinterpret_cast<const T*>(P1), 10350b57cec5SDimitry Andric *reinterpret_cast<const T*>(P2))) 10360b57cec5SDimitry Andric return -1; 10370b57cec5SDimitry Andric if (std::less<T>()(*reinterpret_cast<const T*>(P2), 10380b57cec5SDimitry Andric *reinterpret_cast<const T*>(P1))) 10390b57cec5SDimitry Andric return 1; 10400b57cec5SDimitry Andric return 0; 10410b57cec5SDimitry Andric } 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andric /// get_array_pod_sort_comparator - This is an internal helper function used to 10440b57cec5SDimitry Andric /// get type deduction of T right. 10450b57cec5SDimitry Andric template<typename T> 10460b57cec5SDimitry Andric inline int (*get_array_pod_sort_comparator(const T &)) 10470b57cec5SDimitry Andric (const void*, const void*) { 10480b57cec5SDimitry Andric return array_pod_sort_comparator<T>; 10490b57cec5SDimitry Andric } 10500b57cec5SDimitry Andric 1051*480093f4SDimitry Andric #ifdef EXPENSIVE_CHECKS 1052*480093f4SDimitry Andric namespace detail { 1053*480093f4SDimitry Andric 1054*480093f4SDimitry Andric inline unsigned presortShuffleEntropy() { 1055*480093f4SDimitry Andric static unsigned Result(std::random_device{}()); 1056*480093f4SDimitry Andric return Result; 1057*480093f4SDimitry Andric } 1058*480093f4SDimitry Andric 1059*480093f4SDimitry Andric template <class IteratorTy> 1060*480093f4SDimitry Andric inline void presortShuffle(IteratorTy Start, IteratorTy End) { 1061*480093f4SDimitry Andric std::mt19937 Generator(presortShuffleEntropy()); 1062*480093f4SDimitry Andric std::shuffle(Start, End, Generator); 1063*480093f4SDimitry Andric } 1064*480093f4SDimitry Andric 1065*480093f4SDimitry Andric } // end namespace detail 1066*480093f4SDimitry Andric #endif 1067*480093f4SDimitry Andric 10680b57cec5SDimitry Andric /// array_pod_sort - This sorts an array with the specified start and end 10690b57cec5SDimitry Andric /// extent. This is just like std::sort, except that it calls qsort instead of 10700b57cec5SDimitry Andric /// using an inlined template. qsort is slightly slower than std::sort, but 10710b57cec5SDimitry Andric /// most sorts are not performance critical in LLVM and std::sort has to be 10720b57cec5SDimitry Andric /// template instantiated for each type, leading to significant measured code 10730b57cec5SDimitry Andric /// bloat. This function should generally be used instead of std::sort where 10740b57cec5SDimitry Andric /// possible. 10750b57cec5SDimitry Andric /// 10760b57cec5SDimitry Andric /// This function assumes that you have simple POD-like types that can be 10770b57cec5SDimitry Andric /// compared with std::less and can be moved with memcpy. If this isn't true, 10780b57cec5SDimitry Andric /// you should use std::sort. 10790b57cec5SDimitry Andric /// 10800b57cec5SDimitry Andric /// NOTE: If qsort_r were portable, we could allow a custom comparator and 10810b57cec5SDimitry Andric /// default to std::less. 10820b57cec5SDimitry Andric template<class IteratorTy> 10830b57cec5SDimitry Andric inline void array_pod_sort(IteratorTy Start, IteratorTy End) { 10840b57cec5SDimitry Andric // Don't inefficiently call qsort with one element or trigger undefined 10850b57cec5SDimitry Andric // behavior with an empty sequence. 10860b57cec5SDimitry Andric auto NElts = End - Start; 10870b57cec5SDimitry Andric if (NElts <= 1) return; 10880b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 1089*480093f4SDimitry Andric detail::presortShuffle<IteratorTy>(Start, End); 10900b57cec5SDimitry Andric #endif 10910b57cec5SDimitry Andric qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); 10920b57cec5SDimitry Andric } 10930b57cec5SDimitry Andric 10940b57cec5SDimitry Andric template <class IteratorTy> 10950b57cec5SDimitry Andric inline void array_pod_sort( 10960b57cec5SDimitry Andric IteratorTy Start, IteratorTy End, 10970b57cec5SDimitry Andric int (*Compare)( 10980b57cec5SDimitry Andric const typename std::iterator_traits<IteratorTy>::value_type *, 10990b57cec5SDimitry Andric const typename std::iterator_traits<IteratorTy>::value_type *)) { 11000b57cec5SDimitry Andric // Don't inefficiently call qsort with one element or trigger undefined 11010b57cec5SDimitry Andric // behavior with an empty sequence. 11020b57cec5SDimitry Andric auto NElts = End - Start; 11030b57cec5SDimitry Andric if (NElts <= 1) return; 11040b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 1105*480093f4SDimitry Andric detail::presortShuffle<IteratorTy>(Start, End); 11060b57cec5SDimitry Andric #endif 11070b57cec5SDimitry Andric qsort(&*Start, NElts, sizeof(*Start), 11080b57cec5SDimitry Andric reinterpret_cast<int (*)(const void *, const void *)>(Compare)); 11090b57cec5SDimitry Andric } 11100b57cec5SDimitry Andric 11110b57cec5SDimitry Andric // Provide wrappers to std::sort which shuffle the elements before sorting 11120b57cec5SDimitry Andric // to help uncover non-deterministic behavior (PR35135). 11130b57cec5SDimitry Andric template <typename IteratorTy> 11140b57cec5SDimitry Andric inline void sort(IteratorTy Start, IteratorTy End) { 11150b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 1116*480093f4SDimitry Andric detail::presortShuffle<IteratorTy>(Start, End); 11170b57cec5SDimitry Andric #endif 11180b57cec5SDimitry Andric std::sort(Start, End); 11190b57cec5SDimitry Andric } 11200b57cec5SDimitry Andric 11210b57cec5SDimitry Andric template <typename Container> inline void sort(Container &&C) { 11220b57cec5SDimitry Andric llvm::sort(adl_begin(C), adl_end(C)); 11230b57cec5SDimitry Andric } 11240b57cec5SDimitry Andric 11250b57cec5SDimitry Andric template <typename IteratorTy, typename Compare> 11260b57cec5SDimitry Andric inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) { 11270b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 1128*480093f4SDimitry Andric detail::presortShuffle<IteratorTy>(Start, End); 11290b57cec5SDimitry Andric #endif 11300b57cec5SDimitry Andric std::sort(Start, End, Comp); 11310b57cec5SDimitry Andric } 11320b57cec5SDimitry Andric 11330b57cec5SDimitry Andric template <typename Container, typename Compare> 11340b57cec5SDimitry Andric inline void sort(Container &&C, Compare Comp) { 11350b57cec5SDimitry Andric llvm::sort(adl_begin(C), adl_end(C), Comp); 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric 11380b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 11390b57cec5SDimitry Andric // Extra additions to <algorithm> 11400b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 11410b57cec5SDimitry Andric 11420b57cec5SDimitry Andric /// For a container of pointers, deletes the pointers and then clears the 11430b57cec5SDimitry Andric /// container. 11440b57cec5SDimitry Andric template<typename Container> 11450b57cec5SDimitry Andric void DeleteContainerPointers(Container &C) { 11460b57cec5SDimitry Andric for (auto V : C) 11470b57cec5SDimitry Andric delete V; 11480b57cec5SDimitry Andric C.clear(); 11490b57cec5SDimitry Andric } 11500b57cec5SDimitry Andric 11510b57cec5SDimitry Andric /// In a container of pairs (usually a map) whose second element is a pointer, 11520b57cec5SDimitry Andric /// deletes the second elements and then clears the container. 11530b57cec5SDimitry Andric template<typename Container> 11540b57cec5SDimitry Andric void DeleteContainerSeconds(Container &C) { 11550b57cec5SDimitry Andric for (auto &V : C) 11560b57cec5SDimitry Andric delete V.second; 11570b57cec5SDimitry Andric C.clear(); 11580b57cec5SDimitry Andric } 11590b57cec5SDimitry Andric 11600b57cec5SDimitry Andric /// Get the size of a range. This is a wrapper function around std::distance 11610b57cec5SDimitry Andric /// which is only enabled when the operation is O(1). 11620b57cec5SDimitry Andric template <typename R> 11630b57cec5SDimitry Andric auto size(R &&Range, typename std::enable_if< 11640b57cec5SDimitry Andric std::is_same<typename std::iterator_traits<decltype( 11650b57cec5SDimitry Andric Range.begin())>::iterator_category, 11660b57cec5SDimitry Andric std::random_access_iterator_tag>::value, 11670b57cec5SDimitry Andric void>::type * = nullptr) 11680b57cec5SDimitry Andric -> decltype(std::distance(Range.begin(), Range.end())) { 11690b57cec5SDimitry Andric return std::distance(Range.begin(), Range.end()); 11700b57cec5SDimitry Andric } 11710b57cec5SDimitry Andric 11720b57cec5SDimitry Andric /// Provide wrappers to std::for_each which take ranges instead of having to 11730b57cec5SDimitry Andric /// pass begin/end explicitly. 11740b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 11750b57cec5SDimitry Andric UnaryPredicate for_each(R &&Range, UnaryPredicate P) { 11760b57cec5SDimitry Andric return std::for_each(adl_begin(Range), adl_end(Range), P); 11770b57cec5SDimitry Andric } 11780b57cec5SDimitry Andric 11790b57cec5SDimitry Andric /// Provide wrappers to std::all_of which take ranges instead of having to pass 11800b57cec5SDimitry Andric /// begin/end explicitly. 11810b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 11820b57cec5SDimitry Andric bool all_of(R &&Range, UnaryPredicate P) { 11830b57cec5SDimitry Andric return std::all_of(adl_begin(Range), adl_end(Range), P); 11840b57cec5SDimitry Andric } 11850b57cec5SDimitry Andric 11860b57cec5SDimitry Andric /// Provide wrappers to std::any_of which take ranges instead of having to pass 11870b57cec5SDimitry Andric /// begin/end explicitly. 11880b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 11890b57cec5SDimitry Andric bool any_of(R &&Range, UnaryPredicate P) { 11900b57cec5SDimitry Andric return std::any_of(adl_begin(Range), adl_end(Range), P); 11910b57cec5SDimitry Andric } 11920b57cec5SDimitry Andric 11930b57cec5SDimitry Andric /// Provide wrappers to std::none_of which take ranges instead of having to pass 11940b57cec5SDimitry Andric /// begin/end explicitly. 11950b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 11960b57cec5SDimitry Andric bool none_of(R &&Range, UnaryPredicate P) { 11970b57cec5SDimitry Andric return std::none_of(adl_begin(Range), adl_end(Range), P); 11980b57cec5SDimitry Andric } 11990b57cec5SDimitry Andric 12000b57cec5SDimitry Andric /// Provide wrappers to std::find which take ranges instead of having to pass 12010b57cec5SDimitry Andric /// begin/end explicitly. 12020b57cec5SDimitry Andric template <typename R, typename T> 12030b57cec5SDimitry Andric auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range)) { 12040b57cec5SDimitry Andric return std::find(adl_begin(Range), adl_end(Range), Val); 12050b57cec5SDimitry Andric } 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric /// Provide wrappers to std::find_if which take ranges instead of having to pass 12080b57cec5SDimitry Andric /// begin/end explicitly. 12090b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 12100b57cec5SDimitry Andric auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { 12110b57cec5SDimitry Andric return std::find_if(adl_begin(Range), adl_end(Range), P); 12120b57cec5SDimitry Andric } 12130b57cec5SDimitry Andric 12140b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 12150b57cec5SDimitry Andric auto find_if_not(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { 12160b57cec5SDimitry Andric return std::find_if_not(adl_begin(Range), adl_end(Range), P); 12170b57cec5SDimitry Andric } 12180b57cec5SDimitry Andric 12190b57cec5SDimitry Andric /// Provide wrappers to std::remove_if which take ranges instead of having to 12200b57cec5SDimitry Andric /// pass begin/end explicitly. 12210b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 12220b57cec5SDimitry Andric auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { 12230b57cec5SDimitry Andric return std::remove_if(adl_begin(Range), adl_end(Range), P); 12240b57cec5SDimitry Andric } 12250b57cec5SDimitry Andric 12260b57cec5SDimitry Andric /// Provide wrappers to std::copy_if which take ranges instead of having to 12270b57cec5SDimitry Andric /// pass begin/end explicitly. 12280b57cec5SDimitry Andric template <typename R, typename OutputIt, typename UnaryPredicate> 12290b57cec5SDimitry Andric OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) { 12300b57cec5SDimitry Andric return std::copy_if(adl_begin(Range), adl_end(Range), Out, P); 12310b57cec5SDimitry Andric } 12320b57cec5SDimitry Andric 12330b57cec5SDimitry Andric template <typename R, typename OutputIt> 12340b57cec5SDimitry Andric OutputIt copy(R &&Range, OutputIt Out) { 12350b57cec5SDimitry Andric return std::copy(adl_begin(Range), adl_end(Range), Out); 12360b57cec5SDimitry Andric } 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric /// Wrapper function around std::find to detect if an element exists 12390b57cec5SDimitry Andric /// in a container. 12400b57cec5SDimitry Andric template <typename R, typename E> 12410b57cec5SDimitry Andric bool is_contained(R &&Range, const E &Element) { 12420b57cec5SDimitry Andric return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range); 12430b57cec5SDimitry Andric } 12440b57cec5SDimitry Andric 12450b57cec5SDimitry Andric /// Wrapper function around std::count to count the number of times an element 12460b57cec5SDimitry Andric /// \p Element occurs in the given range \p Range. 12470b57cec5SDimitry Andric template <typename R, typename E> 12480b57cec5SDimitry Andric auto count(R &&Range, const E &Element) -> 12490b57cec5SDimitry Andric typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type { 12500b57cec5SDimitry Andric return std::count(adl_begin(Range), adl_end(Range), Element); 12510b57cec5SDimitry Andric } 12520b57cec5SDimitry Andric 12530b57cec5SDimitry Andric /// Wrapper function around std::count_if to count the number of times an 12540b57cec5SDimitry Andric /// element satisfying a given predicate occurs in a range. 12550b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 12560b57cec5SDimitry Andric auto count_if(R &&Range, UnaryPredicate P) -> 12570b57cec5SDimitry Andric typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type { 12580b57cec5SDimitry Andric return std::count_if(adl_begin(Range), adl_end(Range), P); 12590b57cec5SDimitry Andric } 12600b57cec5SDimitry Andric 12610b57cec5SDimitry Andric /// Wrapper function around std::transform to apply a function to a range and 12620b57cec5SDimitry Andric /// store the result elsewhere. 12630b57cec5SDimitry Andric template <typename R, typename OutputIt, typename UnaryPredicate> 12640b57cec5SDimitry Andric OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P) { 12650b57cec5SDimitry Andric return std::transform(adl_begin(Range), adl_end(Range), d_first, P); 12660b57cec5SDimitry Andric } 12670b57cec5SDimitry Andric 12680b57cec5SDimitry Andric /// Provide wrappers to std::partition which take ranges instead of having to 12690b57cec5SDimitry Andric /// pass begin/end explicitly. 12700b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 12710b57cec5SDimitry Andric auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) { 12720b57cec5SDimitry Andric return std::partition(adl_begin(Range), adl_end(Range), P); 12730b57cec5SDimitry Andric } 12740b57cec5SDimitry Andric 12750b57cec5SDimitry Andric /// Provide wrappers to std::lower_bound which take ranges instead of having to 12760b57cec5SDimitry Andric /// pass begin/end explicitly. 12770b57cec5SDimitry Andric template <typename R, typename T> 12780b57cec5SDimitry Andric auto lower_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) { 12790b57cec5SDimitry Andric return std::lower_bound(adl_begin(Range), adl_end(Range), 12800b57cec5SDimitry Andric std::forward<T>(Value)); 12810b57cec5SDimitry Andric } 12820b57cec5SDimitry Andric 12830b57cec5SDimitry Andric template <typename R, typename T, typename Compare> 12840b57cec5SDimitry Andric auto lower_bound(R &&Range, T &&Value, Compare C) 12850b57cec5SDimitry Andric -> decltype(adl_begin(Range)) { 12860b57cec5SDimitry Andric return std::lower_bound(adl_begin(Range), adl_end(Range), 12870b57cec5SDimitry Andric std::forward<T>(Value), C); 12880b57cec5SDimitry Andric } 12890b57cec5SDimitry Andric 12900b57cec5SDimitry Andric /// Provide wrappers to std::upper_bound which take ranges instead of having to 12910b57cec5SDimitry Andric /// pass begin/end explicitly. 12920b57cec5SDimitry Andric template <typename R, typename T> 12930b57cec5SDimitry Andric auto upper_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) { 12940b57cec5SDimitry Andric return std::upper_bound(adl_begin(Range), adl_end(Range), 12950b57cec5SDimitry Andric std::forward<T>(Value)); 12960b57cec5SDimitry Andric } 12970b57cec5SDimitry Andric 12980b57cec5SDimitry Andric template <typename R, typename T, typename Compare> 12990b57cec5SDimitry Andric auto upper_bound(R &&Range, T &&Value, Compare C) 13000b57cec5SDimitry Andric -> decltype(adl_begin(Range)) { 13010b57cec5SDimitry Andric return std::upper_bound(adl_begin(Range), adl_end(Range), 13020b57cec5SDimitry Andric std::forward<T>(Value), C); 13030b57cec5SDimitry Andric } 13040b57cec5SDimitry Andric 13050b57cec5SDimitry Andric template <typename R> 13060b57cec5SDimitry Andric void stable_sort(R &&Range) { 13070b57cec5SDimitry Andric std::stable_sort(adl_begin(Range), adl_end(Range)); 13080b57cec5SDimitry Andric } 13090b57cec5SDimitry Andric 13100b57cec5SDimitry Andric template <typename R, typename Compare> 13110b57cec5SDimitry Andric void stable_sort(R &&Range, Compare C) { 13120b57cec5SDimitry Andric std::stable_sort(adl_begin(Range), adl_end(Range), C); 13130b57cec5SDimitry Andric } 13140b57cec5SDimitry Andric 13150b57cec5SDimitry Andric /// Binary search for the first iterator in a range where a predicate is false. 13160b57cec5SDimitry Andric /// Requires that C is always true below some limit, and always false above it. 13170b57cec5SDimitry Andric template <typename R, typename Predicate, 13180b57cec5SDimitry Andric typename Val = decltype(*adl_begin(std::declval<R>()))> 13190b57cec5SDimitry Andric auto partition_point(R &&Range, Predicate P) -> decltype(adl_begin(Range)) { 13200b57cec5SDimitry Andric return std::partition_point(adl_begin(Range), adl_end(Range), P); 13210b57cec5SDimitry Andric } 13220b57cec5SDimitry Andric 13230b57cec5SDimitry Andric /// Wrapper function around std::equal to detect if all elements 13240b57cec5SDimitry Andric /// in a container are same. 13250b57cec5SDimitry Andric template <typename R> 13260b57cec5SDimitry Andric bool is_splat(R &&Range) { 13270b57cec5SDimitry Andric size_t range_size = size(Range); 13280b57cec5SDimitry Andric return range_size != 0 && (range_size == 1 || 13290b57cec5SDimitry Andric std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range))); 13300b57cec5SDimitry Andric } 13310b57cec5SDimitry Andric 13320b57cec5SDimitry Andric /// Provide a container algorithm similar to C++ Library Fundamentals v2's 13330b57cec5SDimitry Andric /// `erase_if` which is equivalent to: 13340b57cec5SDimitry Andric /// 13350b57cec5SDimitry Andric /// C.erase(remove_if(C, pred), C.end()); 13360b57cec5SDimitry Andric /// 13370b57cec5SDimitry Andric /// This version works for any container with an erase method call accepting 13380b57cec5SDimitry Andric /// two iterators. 13390b57cec5SDimitry Andric template <typename Container, typename UnaryPredicate> 13400b57cec5SDimitry Andric void erase_if(Container &C, UnaryPredicate P) { 13410b57cec5SDimitry Andric C.erase(remove_if(C, P), C.end()); 13420b57cec5SDimitry Andric } 13430b57cec5SDimitry Andric 13440b57cec5SDimitry Andric /// Given a sequence container Cont, replace the range [ContIt, ContEnd) with 13450b57cec5SDimitry Andric /// the range [ValIt, ValEnd) (which is not from the same container). 13460b57cec5SDimitry Andric template<typename Container, typename RandomAccessIterator> 13470b57cec5SDimitry Andric void replace(Container &Cont, typename Container::iterator ContIt, 13480b57cec5SDimitry Andric typename Container::iterator ContEnd, RandomAccessIterator ValIt, 13490b57cec5SDimitry Andric RandomAccessIterator ValEnd) { 13500b57cec5SDimitry Andric while (true) { 13510b57cec5SDimitry Andric if (ValIt == ValEnd) { 13520b57cec5SDimitry Andric Cont.erase(ContIt, ContEnd); 13530b57cec5SDimitry Andric return; 13540b57cec5SDimitry Andric } else if (ContIt == ContEnd) { 13550b57cec5SDimitry Andric Cont.insert(ContIt, ValIt, ValEnd); 13560b57cec5SDimitry Andric return; 13570b57cec5SDimitry Andric } 13580b57cec5SDimitry Andric *ContIt++ = *ValIt++; 13590b57cec5SDimitry Andric } 13600b57cec5SDimitry Andric } 13610b57cec5SDimitry Andric 13620b57cec5SDimitry Andric /// Given a sequence container Cont, replace the range [ContIt, ContEnd) with 13630b57cec5SDimitry Andric /// the range R. 13640b57cec5SDimitry Andric template<typename Container, typename Range = std::initializer_list< 13650b57cec5SDimitry Andric typename Container::value_type>> 13660b57cec5SDimitry Andric void replace(Container &Cont, typename Container::iterator ContIt, 13670b57cec5SDimitry Andric typename Container::iterator ContEnd, Range R) { 13680b57cec5SDimitry Andric replace(Cont, ContIt, ContEnd, R.begin(), R.end()); 13690b57cec5SDimitry Andric } 13700b57cec5SDimitry Andric 13710b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13720b57cec5SDimitry Andric // Extra additions to <memory> 13730b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13740b57cec5SDimitry Andric 13750b57cec5SDimitry Andric struct FreeDeleter { 13760b57cec5SDimitry Andric void operator()(void* v) { 13770b57cec5SDimitry Andric ::free(v); 13780b57cec5SDimitry Andric } 13790b57cec5SDimitry Andric }; 13800b57cec5SDimitry Andric 13810b57cec5SDimitry Andric template<typename First, typename Second> 13820b57cec5SDimitry Andric struct pair_hash { 13830b57cec5SDimitry Andric size_t operator()(const std::pair<First, Second> &P) const { 13840b57cec5SDimitry Andric return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second); 13850b57cec5SDimitry Andric } 13860b57cec5SDimitry Andric }; 13870b57cec5SDimitry Andric 13880b57cec5SDimitry Andric /// Binary functor that adapts to any other binary functor after dereferencing 13890b57cec5SDimitry Andric /// operands. 13900b57cec5SDimitry Andric template <typename T> struct deref { 13910b57cec5SDimitry Andric T func; 13920b57cec5SDimitry Andric 13930b57cec5SDimitry Andric // Could be further improved to cope with non-derivable functors and 13940b57cec5SDimitry Andric // non-binary functors (should be a variadic template member function 13950b57cec5SDimitry Andric // operator()). 13960b57cec5SDimitry Andric template <typename A, typename B> 13970b57cec5SDimitry Andric auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) { 13980b57cec5SDimitry Andric assert(lhs); 13990b57cec5SDimitry Andric assert(rhs); 14000b57cec5SDimitry Andric return func(*lhs, *rhs); 14010b57cec5SDimitry Andric } 14020b57cec5SDimitry Andric }; 14030b57cec5SDimitry Andric 14040b57cec5SDimitry Andric namespace detail { 14050b57cec5SDimitry Andric 14060b57cec5SDimitry Andric template <typename R> class enumerator_iter; 14070b57cec5SDimitry Andric 14080b57cec5SDimitry Andric template <typename R> struct result_pair { 14090b57cec5SDimitry Andric using value_reference = 14100b57cec5SDimitry Andric typename std::iterator_traits<IterOfRange<R>>::reference; 14110b57cec5SDimitry Andric 14120b57cec5SDimitry Andric friend class enumerator_iter<R>; 14130b57cec5SDimitry Andric 14140b57cec5SDimitry Andric result_pair() = default; 14150b57cec5SDimitry Andric result_pair(std::size_t Index, IterOfRange<R> Iter) 14160b57cec5SDimitry Andric : Index(Index), Iter(Iter) {} 14170b57cec5SDimitry Andric 1418*480093f4SDimitry Andric result_pair<R>(const result_pair<R> &Other) 1419*480093f4SDimitry Andric : Index(Other.Index), Iter(Other.Iter) {} 14200b57cec5SDimitry Andric result_pair<R> &operator=(const result_pair<R> &Other) { 14210b57cec5SDimitry Andric Index = Other.Index; 14220b57cec5SDimitry Andric Iter = Other.Iter; 14230b57cec5SDimitry Andric return *this; 14240b57cec5SDimitry Andric } 14250b57cec5SDimitry Andric 14260b57cec5SDimitry Andric std::size_t index() const { return Index; } 14270b57cec5SDimitry Andric const value_reference value() const { return *Iter; } 14280b57cec5SDimitry Andric value_reference value() { return *Iter; } 14290b57cec5SDimitry Andric 14300b57cec5SDimitry Andric private: 14310b57cec5SDimitry Andric std::size_t Index = std::numeric_limits<std::size_t>::max(); 14320b57cec5SDimitry Andric IterOfRange<R> Iter; 14330b57cec5SDimitry Andric }; 14340b57cec5SDimitry Andric 14350b57cec5SDimitry Andric template <typename R> 14360b57cec5SDimitry Andric class enumerator_iter 14370b57cec5SDimitry Andric : public iterator_facade_base< 14380b57cec5SDimitry Andric enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>, 14390b57cec5SDimitry Andric typename std::iterator_traits<IterOfRange<R>>::difference_type, 14400b57cec5SDimitry Andric typename std::iterator_traits<IterOfRange<R>>::pointer, 14410b57cec5SDimitry Andric typename std::iterator_traits<IterOfRange<R>>::reference> { 14420b57cec5SDimitry Andric using result_type = result_pair<R>; 14430b57cec5SDimitry Andric 14440b57cec5SDimitry Andric public: 14450b57cec5SDimitry Andric explicit enumerator_iter(IterOfRange<R> EndIter) 14460b57cec5SDimitry Andric : Result(std::numeric_limits<size_t>::max(), EndIter) {} 14470b57cec5SDimitry Andric 14480b57cec5SDimitry Andric enumerator_iter(std::size_t Index, IterOfRange<R> Iter) 14490b57cec5SDimitry Andric : Result(Index, Iter) {} 14500b57cec5SDimitry Andric 14510b57cec5SDimitry Andric result_type &operator*() { return Result; } 14520b57cec5SDimitry Andric const result_type &operator*() const { return Result; } 14530b57cec5SDimitry Andric 14540b57cec5SDimitry Andric enumerator_iter<R> &operator++() { 14550b57cec5SDimitry Andric assert(Result.Index != std::numeric_limits<size_t>::max()); 14560b57cec5SDimitry Andric ++Result.Iter; 14570b57cec5SDimitry Andric ++Result.Index; 14580b57cec5SDimitry Andric return *this; 14590b57cec5SDimitry Andric } 14600b57cec5SDimitry Andric 14610b57cec5SDimitry Andric bool operator==(const enumerator_iter<R> &RHS) const { 14620b57cec5SDimitry Andric // Don't compare indices here, only iterators. It's possible for an end 14630b57cec5SDimitry Andric // iterator to have different indices depending on whether it was created 14640b57cec5SDimitry Andric // by calling std::end() versus incrementing a valid iterator. 14650b57cec5SDimitry Andric return Result.Iter == RHS.Result.Iter; 14660b57cec5SDimitry Andric } 14670b57cec5SDimitry Andric 1468*480093f4SDimitry Andric enumerator_iter<R>(const enumerator_iter<R> &Other) : Result(Other.Result) {} 14690b57cec5SDimitry Andric enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) { 14700b57cec5SDimitry Andric Result = Other.Result; 14710b57cec5SDimitry Andric return *this; 14720b57cec5SDimitry Andric } 14730b57cec5SDimitry Andric 14740b57cec5SDimitry Andric private: 14750b57cec5SDimitry Andric result_type Result; 14760b57cec5SDimitry Andric }; 14770b57cec5SDimitry Andric 14780b57cec5SDimitry Andric template <typename R> class enumerator { 14790b57cec5SDimitry Andric public: 14800b57cec5SDimitry Andric explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {} 14810b57cec5SDimitry Andric 14820b57cec5SDimitry Andric enumerator_iter<R> begin() { 14830b57cec5SDimitry Andric return enumerator_iter<R>(0, std::begin(TheRange)); 14840b57cec5SDimitry Andric } 14850b57cec5SDimitry Andric 14860b57cec5SDimitry Andric enumerator_iter<R> end() { 14870b57cec5SDimitry Andric return enumerator_iter<R>(std::end(TheRange)); 14880b57cec5SDimitry Andric } 14890b57cec5SDimitry Andric 14900b57cec5SDimitry Andric private: 14910b57cec5SDimitry Andric R TheRange; 14920b57cec5SDimitry Andric }; 14930b57cec5SDimitry Andric 14940b57cec5SDimitry Andric } // end namespace detail 14950b57cec5SDimitry Andric 14960b57cec5SDimitry Andric /// Given an input range, returns a new range whose values are are pair (A,B) 14970b57cec5SDimitry Andric /// such that A is the 0-based index of the item in the sequence, and B is 14980b57cec5SDimitry Andric /// the value from the original sequence. Example: 14990b57cec5SDimitry Andric /// 15000b57cec5SDimitry Andric /// std::vector<char> Items = {'A', 'B', 'C', 'D'}; 15010b57cec5SDimitry Andric /// for (auto X : enumerate(Items)) { 15020b57cec5SDimitry Andric /// printf("Item %d - %c\n", X.index(), X.value()); 15030b57cec5SDimitry Andric /// } 15040b57cec5SDimitry Andric /// 15050b57cec5SDimitry Andric /// Output: 15060b57cec5SDimitry Andric /// Item 0 - A 15070b57cec5SDimitry Andric /// Item 1 - B 15080b57cec5SDimitry Andric /// Item 2 - C 15090b57cec5SDimitry Andric /// Item 3 - D 15100b57cec5SDimitry Andric /// 15110b57cec5SDimitry Andric template <typename R> detail::enumerator<R> enumerate(R &&TheRange) { 15120b57cec5SDimitry Andric return detail::enumerator<R>(std::forward<R>(TheRange)); 15130b57cec5SDimitry Andric } 15140b57cec5SDimitry Andric 15150b57cec5SDimitry Andric namespace detail { 15160b57cec5SDimitry Andric 15170b57cec5SDimitry Andric template <typename F, typename Tuple, std::size_t... I> 15188bcb0991SDimitry Andric auto apply_tuple_impl(F &&f, Tuple &&t, std::index_sequence<I...>) 15190b57cec5SDimitry Andric -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...)) { 15200b57cec5SDimitry Andric return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...); 15210b57cec5SDimitry Andric } 15220b57cec5SDimitry Andric 15230b57cec5SDimitry Andric } // end namespace detail 15240b57cec5SDimitry Andric 15250b57cec5SDimitry Andric /// Given an input tuple (a1, a2, ..., an), pass the arguments of the 15260b57cec5SDimitry Andric /// tuple variadically to f as if by calling f(a1, a2, ..., an) and 15270b57cec5SDimitry Andric /// return the result. 15280b57cec5SDimitry Andric template <typename F, typename Tuple> 15290b57cec5SDimitry Andric auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl( 15300b57cec5SDimitry Andric std::forward<F>(f), std::forward<Tuple>(t), 15318bcb0991SDimitry Andric std::make_index_sequence< 15320b57cec5SDimitry Andric std::tuple_size<typename std::decay<Tuple>::type>::value>{})) { 15338bcb0991SDimitry Andric using Indices = std::make_index_sequence< 15340b57cec5SDimitry Andric std::tuple_size<typename std::decay<Tuple>::type>::value>; 15350b57cec5SDimitry Andric 15360b57cec5SDimitry Andric return detail::apply_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t), 15370b57cec5SDimitry Andric Indices{}); 15380b57cec5SDimitry Andric } 15390b57cec5SDimitry Andric 15400b57cec5SDimitry Andric /// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N) 15410b57cec5SDimitry Andric /// time. Not meant for use with random-access iterators. 15420b57cec5SDimitry Andric template <typename IterTy> 15430b57cec5SDimitry Andric bool hasNItems( 15440b57cec5SDimitry Andric IterTy &&Begin, IterTy &&End, unsigned N, 15450b57cec5SDimitry Andric typename std::enable_if< 15460b57cec5SDimitry Andric !std::is_same< 15470b57cec5SDimitry Andric typename std::iterator_traits<typename std::remove_reference< 15480b57cec5SDimitry Andric decltype(Begin)>::type>::iterator_category, 15490b57cec5SDimitry Andric std::random_access_iterator_tag>::value, 15500b57cec5SDimitry Andric void>::type * = nullptr) { 15510b57cec5SDimitry Andric for (; N; --N, ++Begin) 15520b57cec5SDimitry Andric if (Begin == End) 15530b57cec5SDimitry Andric return false; // Too few. 15540b57cec5SDimitry Andric return Begin == End; 15550b57cec5SDimitry Andric } 15560b57cec5SDimitry Andric 15570b57cec5SDimitry Andric /// Return true if the sequence [Begin, End) has N or more items. Runs in O(N) 15580b57cec5SDimitry Andric /// time. Not meant for use with random-access iterators. 15590b57cec5SDimitry Andric template <typename IterTy> 15600b57cec5SDimitry Andric bool hasNItemsOrMore( 15610b57cec5SDimitry Andric IterTy &&Begin, IterTy &&End, unsigned N, 15620b57cec5SDimitry Andric typename std::enable_if< 15630b57cec5SDimitry Andric !std::is_same< 15640b57cec5SDimitry Andric typename std::iterator_traits<typename std::remove_reference< 15650b57cec5SDimitry Andric decltype(Begin)>::type>::iterator_category, 15660b57cec5SDimitry Andric std::random_access_iterator_tag>::value, 15670b57cec5SDimitry Andric void>::type * = nullptr) { 15680b57cec5SDimitry Andric for (; N; --N, ++Begin) 15690b57cec5SDimitry Andric if (Begin == End) 15700b57cec5SDimitry Andric return false; // Too few. 15710b57cec5SDimitry Andric return true; 15720b57cec5SDimitry Andric } 15730b57cec5SDimitry Andric 15740b57cec5SDimitry Andric /// Returns a raw pointer that represents the same address as the argument. 15750b57cec5SDimitry Andric /// 15760b57cec5SDimitry Andric /// The late bound return should be removed once we move to C++14 to better 15770b57cec5SDimitry Andric /// align with the C++20 declaration. Also, this implementation can be removed 15780b57cec5SDimitry Andric /// once we move to C++20 where it's defined as std::to_addres() 15790b57cec5SDimitry Andric /// 15800b57cec5SDimitry Andric /// The std::pointer_traits<>::to_address(p) variations of these overloads has 15810b57cec5SDimitry Andric /// not been implemented. 15820b57cec5SDimitry Andric template <class Ptr> auto to_address(const Ptr &P) -> decltype(P.operator->()) { 15830b57cec5SDimitry Andric return P.operator->(); 15840b57cec5SDimitry Andric } 15850b57cec5SDimitry Andric template <class T> constexpr T *to_address(T *P) { return P; } 15860b57cec5SDimitry Andric 15870b57cec5SDimitry Andric } // end namespace llvm 15880b57cec5SDimitry Andric 15890b57cec5SDimitry Andric #endif // LLVM_ADT_STLEXTRAS_H 1590