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" 20fe6060f1SDimitry Andric #include "llvm/ADT/STLForwardCompat.h" 210b57cec5SDimitry Andric #include "llvm/ADT/iterator.h" 220b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 230b57cec5SDimitry Andric #include "llvm/Config/abi-breaking.h" 240b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 250b57cec5SDimitry Andric #include <algorithm> 260b57cec5SDimitry Andric #include <cassert> 270b57cec5SDimitry Andric #include <cstddef> 280b57cec5SDimitry Andric #include <cstdint> 290b57cec5SDimitry Andric #include <cstdlib> 300b57cec5SDimitry Andric #include <functional> 310b57cec5SDimitry Andric #include <initializer_list> 320b57cec5SDimitry Andric #include <iterator> 330b57cec5SDimitry Andric #include <limits> 340b57cec5SDimitry Andric #include <memory> 350b57cec5SDimitry Andric #include <tuple> 360b57cec5SDimitry Andric #include <type_traits> 370b57cec5SDimitry Andric #include <utility> 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 400b57cec5SDimitry Andric #include <random> // for std::mt19937 410b57cec5SDimitry Andric #endif 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric namespace llvm { 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric // Only used by compiler if both template types are the same. Useful when 460b57cec5SDimitry Andric // using SFINAE to test for the existence of member functions. 470b57cec5SDimitry Andric template <typename T, T> struct SameType; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric namespace detail { 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric template <typename RangeT> 520b57cec5SDimitry Andric using IterOfRange = decltype(std::begin(std::declval<RangeT &>())); 530b57cec5SDimitry Andric 545ffd83dbSDimitry Andric template <typename RangeT> 555ffd83dbSDimitry Andric using ValueOfRange = typename std::remove_reference<decltype( 565ffd83dbSDimitry Andric *std::begin(std::declval<RangeT &>()))>::type; 575ffd83dbSDimitry Andric 580b57cec5SDimitry Andric } // end namespace detail 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 610b57cec5SDimitry Andric // Extra additions to <type_traits> 620b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric template <typename T> struct make_const_ptr { 650b57cec5SDimitry Andric using type = 660b57cec5SDimitry Andric typename std::add_pointer<typename std::add_const<T>::type>::type; 670b57cec5SDimitry Andric }; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric template <typename T> struct make_const_ref { 700b57cec5SDimitry Andric using type = typename std::add_lvalue_reference< 710b57cec5SDimitry Andric typename std::add_const<T>::type>::type; 720b57cec5SDimitry Andric }; 730b57cec5SDimitry Andric 745ffd83dbSDimitry Andric namespace detail { 755ffd83dbSDimitry Andric template <typename...> using void_t = void; 765ffd83dbSDimitry Andric template <class, template <class...> class Op, class... Args> struct detector { 775ffd83dbSDimitry Andric using value_t = std::false_type; 785ffd83dbSDimitry Andric }; 795ffd83dbSDimitry Andric template <template <class...> class Op, class... Args> 805ffd83dbSDimitry Andric struct detector<void_t<Op<Args...>>, Op, Args...> { 815ffd83dbSDimitry Andric using value_t = std::true_type; 825ffd83dbSDimitry Andric }; 835ffd83dbSDimitry Andric } // end namespace detail 845ffd83dbSDimitry Andric 85fe6060f1SDimitry Andric /// Detects if a given trait holds for some set of arguments 'Args'. 86fe6060f1SDimitry Andric /// For example, the given trait could be used to detect if a given type 87fe6060f1SDimitry Andric /// has a copy assignment operator: 88fe6060f1SDimitry Andric /// template<class T> 89fe6060f1SDimitry Andric /// using has_copy_assign_t = decltype(std::declval<T&>() 90fe6060f1SDimitry Andric /// = std::declval<const T&>()); 91fe6060f1SDimitry Andric /// bool fooHasCopyAssign = is_detected<has_copy_assign_t, FooClass>::value; 925ffd83dbSDimitry Andric template <template <class...> class Op, class... Args> 935ffd83dbSDimitry Andric using is_detected = typename detail::detector<void, Op, Args...>::value_t; 945ffd83dbSDimitry Andric 955ffd83dbSDimitry Andric namespace detail { 965ffd83dbSDimitry Andric template <typename Callable, typename... Args> 975ffd83dbSDimitry Andric using is_invocable = 985ffd83dbSDimitry Andric decltype(std::declval<Callable &>()(std::declval<Args>()...)); 995ffd83dbSDimitry Andric } // namespace detail 1005ffd83dbSDimitry Andric 101fe6060f1SDimitry Andric /// Check if a Callable type can be invoked with the given set of arg types. 1025ffd83dbSDimitry Andric template <typename Callable, typename... Args> 1035ffd83dbSDimitry Andric using is_invocable = is_detected<detail::is_invocable, Callable, Args...>; 1045ffd83dbSDimitry Andric 1055ffd83dbSDimitry Andric /// This class provides various trait information about a callable object. 1065ffd83dbSDimitry Andric /// * To access the number of arguments: Traits::num_args 1075ffd83dbSDimitry Andric /// * To access the type of an argument: Traits::arg_t<Index> 1085ffd83dbSDimitry Andric /// * To access the type of the result: Traits::result_t 1095ffd83dbSDimitry Andric template <typename T, bool isClass = std::is_class<T>::value> 1105ffd83dbSDimitry Andric struct function_traits : public function_traits<decltype(&T::operator())> {}; 1115ffd83dbSDimitry Andric 1125ffd83dbSDimitry Andric /// Overload for class function types. 1135ffd83dbSDimitry Andric template <typename ClassType, typename ReturnType, typename... Args> 1145ffd83dbSDimitry Andric struct function_traits<ReturnType (ClassType::*)(Args...) const, false> { 1155ffd83dbSDimitry Andric /// The number of arguments to this function. 1165ffd83dbSDimitry Andric enum { num_args = sizeof...(Args) }; 1175ffd83dbSDimitry Andric 1185ffd83dbSDimitry Andric /// The result type of this function. 1195ffd83dbSDimitry Andric using result_t = ReturnType; 1205ffd83dbSDimitry Andric 1215ffd83dbSDimitry Andric /// The type of an argument to this function. 1225ffd83dbSDimitry Andric template <size_t Index> 1235ffd83dbSDimitry Andric using arg_t = typename std::tuple_element<Index, std::tuple<Args...>>::type; 1245ffd83dbSDimitry Andric }; 1255ffd83dbSDimitry Andric /// Overload for class function types. 1265ffd83dbSDimitry Andric template <typename ClassType, typename ReturnType, typename... Args> 1275ffd83dbSDimitry Andric struct function_traits<ReturnType (ClassType::*)(Args...), false> 1285ffd83dbSDimitry Andric : function_traits<ReturnType (ClassType::*)(Args...) const> {}; 1295ffd83dbSDimitry Andric /// Overload for non-class function types. 1305ffd83dbSDimitry Andric template <typename ReturnType, typename... Args> 1315ffd83dbSDimitry Andric struct function_traits<ReturnType (*)(Args...), false> { 1325ffd83dbSDimitry Andric /// The number of arguments to this function. 1335ffd83dbSDimitry Andric enum { num_args = sizeof...(Args) }; 1345ffd83dbSDimitry Andric 1355ffd83dbSDimitry Andric /// The result type of this function. 1365ffd83dbSDimitry Andric using result_t = ReturnType; 1375ffd83dbSDimitry Andric 1385ffd83dbSDimitry Andric /// The type of an argument to this function. 1395ffd83dbSDimitry Andric template <size_t i> 1405ffd83dbSDimitry Andric using arg_t = typename std::tuple_element<i, std::tuple<Args...>>::type; 1415ffd83dbSDimitry Andric }; 1425ffd83dbSDimitry Andric /// Overload for non-class function type references. 1435ffd83dbSDimitry Andric template <typename ReturnType, typename... Args> 1445ffd83dbSDimitry Andric struct function_traits<ReturnType (&)(Args...), false> 1455ffd83dbSDimitry Andric : public function_traits<ReturnType (*)(Args...)> {}; 1465ffd83dbSDimitry Andric 147*0eae32dcSDimitry Andric /// traits class for checking whether type T is one of any of the given 148*0eae32dcSDimitry Andric /// types in the variadic list. 149*0eae32dcSDimitry Andric template <typename T, typename... Ts> 150*0eae32dcSDimitry Andric using is_one_of = disjunction<std::is_same<T, Ts>...>; 151*0eae32dcSDimitry Andric 152*0eae32dcSDimitry Andric /// traits class for checking whether type T is a base class for all 153*0eae32dcSDimitry Andric /// the given types in the variadic list. 154*0eae32dcSDimitry Andric template <typename T, typename... Ts> 155*0eae32dcSDimitry Andric using are_base_of = conjunction<std::is_base_of<T, Ts>...>; 156*0eae32dcSDimitry Andric 157*0eae32dcSDimitry Andric namespace detail { 158*0eae32dcSDimitry Andric template <typename T, typename... Us> struct TypesAreDistinct; 159*0eae32dcSDimitry Andric template <typename T, typename... Us> 160*0eae32dcSDimitry Andric struct TypesAreDistinct 161*0eae32dcSDimitry Andric : std::integral_constant<bool, !is_one_of<T, Us...>::value && 162*0eae32dcSDimitry Andric TypesAreDistinct<Us...>::value> {}; 163*0eae32dcSDimitry Andric template <typename T> struct TypesAreDistinct<T> : std::true_type {}; 164*0eae32dcSDimitry Andric } // namespace detail 165*0eae32dcSDimitry Andric 166*0eae32dcSDimitry Andric /// Determine if all types in Ts are distinct. 167*0eae32dcSDimitry Andric /// 168*0eae32dcSDimitry Andric /// Useful to statically assert when Ts is intended to describe a non-multi set 169*0eae32dcSDimitry Andric /// of types. 170*0eae32dcSDimitry Andric /// 171*0eae32dcSDimitry Andric /// Expensive (currently quadratic in sizeof(Ts...)), and so should only be 172*0eae32dcSDimitry Andric /// asserted once per instantiation of a type which requires it. 173*0eae32dcSDimitry Andric template <typename... Ts> struct TypesAreDistinct; 174*0eae32dcSDimitry Andric template <> struct TypesAreDistinct<> : std::true_type {}; 175*0eae32dcSDimitry Andric template <typename... Ts> 176*0eae32dcSDimitry Andric struct TypesAreDistinct 177*0eae32dcSDimitry Andric : std::integral_constant<bool, detail::TypesAreDistinct<Ts...>::value> {}; 178*0eae32dcSDimitry Andric 179*0eae32dcSDimitry Andric /// Find the first index where a type appears in a list of types. 180*0eae32dcSDimitry Andric /// 181*0eae32dcSDimitry Andric /// FirstIndexOfType<T, Us...>::value is the first index of T in Us. 182*0eae32dcSDimitry Andric /// 183*0eae32dcSDimitry Andric /// Typically only meaningful when it is otherwise statically known that the 184*0eae32dcSDimitry Andric /// type pack has no duplicate types. This should be guaranteed explicitly with 185*0eae32dcSDimitry Andric /// static_assert(TypesAreDistinct<Us...>::value). 186*0eae32dcSDimitry Andric /// 187*0eae32dcSDimitry Andric /// It is a compile-time error to instantiate when T is not present in Us, i.e. 188*0eae32dcSDimitry Andric /// if is_one_of<T, Us...>::value is false. 189*0eae32dcSDimitry Andric template <typename T, typename... Us> struct FirstIndexOfType; 190*0eae32dcSDimitry Andric template <typename T, typename U, typename... Us> 191*0eae32dcSDimitry Andric struct FirstIndexOfType<T, U, Us...> 192*0eae32dcSDimitry Andric : std::integral_constant<size_t, 1 + FirstIndexOfType<T, Us...>::value> {}; 193*0eae32dcSDimitry Andric template <typename T, typename... Us> 194*0eae32dcSDimitry Andric struct FirstIndexOfType<T, T, Us...> : std::integral_constant<size_t, 0> {}; 195*0eae32dcSDimitry Andric 196*0eae32dcSDimitry Andric /// Find the type at a given index in a list of types. 197*0eae32dcSDimitry Andric /// 198*0eae32dcSDimitry Andric /// TypeAtIndex<I, Ts...> is the type at index I in Ts. 199*0eae32dcSDimitry Andric template <size_t I, typename... Ts> 200*0eae32dcSDimitry Andric using TypeAtIndex = std::tuple_element_t<I, std::tuple<Ts...>>; 201*0eae32dcSDimitry Andric 2020b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2030b57cec5SDimitry Andric // Extra additions to <functional> 2040b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2050b57cec5SDimitry Andric 2060b57cec5SDimitry Andric template <class Ty> struct identity { 2070b57cec5SDimitry Andric using argument_type = Ty; 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric Ty &operator()(Ty &self) const { 2100b57cec5SDimitry Andric return self; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric const Ty &operator()(const Ty &self) const { 2130b57cec5SDimitry Andric return self; 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric }; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric /// An efficient, type-erasing, non-owning reference to a callable. This is 2180b57cec5SDimitry Andric /// intended for use as the type of a function parameter that is not used 2190b57cec5SDimitry Andric /// after the function in question returns. 2200b57cec5SDimitry Andric /// 2210b57cec5SDimitry Andric /// This class does not own the callable, so it is not in general safe to store 2220b57cec5SDimitry Andric /// a function_ref. 2230b57cec5SDimitry Andric template<typename Fn> class function_ref; 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric template<typename Ret, typename ...Params> 2260b57cec5SDimitry Andric class function_ref<Ret(Params...)> { 2270b57cec5SDimitry Andric Ret (*callback)(intptr_t callable, Params ...params) = nullptr; 2280b57cec5SDimitry Andric intptr_t callable; 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric template<typename Callable> 2310b57cec5SDimitry Andric static Ret callback_fn(intptr_t callable, Params ...params) { 2320b57cec5SDimitry Andric return (*reinterpret_cast<Callable*>(callable))( 2330b57cec5SDimitry Andric std::forward<Params>(params)...); 2340b57cec5SDimitry Andric } 2350b57cec5SDimitry Andric 2360b57cec5SDimitry Andric public: 2370b57cec5SDimitry Andric function_ref() = default; 2380b57cec5SDimitry Andric function_ref(std::nullptr_t) {} 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric template <typename Callable> 2415ffd83dbSDimitry Andric function_ref( 2425ffd83dbSDimitry Andric Callable &&callable, 243e8d8bef9SDimitry Andric // This is not the copy-constructor. 244fe6060f1SDimitry Andric std::enable_if_t<!std::is_same<remove_cvref_t<Callable>, 245e8d8bef9SDimitry Andric function_ref>::value> * = nullptr, 246e8d8bef9SDimitry Andric // Functor must be callable and return a suitable type. 247e8d8bef9SDimitry Andric std::enable_if_t<std::is_void<Ret>::value || 248e8d8bef9SDimitry Andric std::is_convertible<decltype(std::declval<Callable>()( 249e8d8bef9SDimitry Andric std::declval<Params>()...)), 250e8d8bef9SDimitry Andric Ret>::value> * = nullptr) 2510b57cec5SDimitry Andric : callback(callback_fn<typename std::remove_reference<Callable>::type>), 2520b57cec5SDimitry Andric callable(reinterpret_cast<intptr_t>(&callable)) {} 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric Ret operator()(Params ...params) const { 2550b57cec5SDimitry Andric return callback(callable, std::forward<Params>(params)...); 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric 2585ffd83dbSDimitry Andric explicit operator bool() const { return callback; } 2590b57cec5SDimitry Andric }; 2600b57cec5SDimitry Andric 2610b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2620b57cec5SDimitry Andric // Extra additions to <iterator> 2630b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric namespace adl_detail { 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric using std::begin; 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric template <typename ContainerTy> 2705ffd83dbSDimitry Andric decltype(auto) adl_begin(ContainerTy &&container) { 2710b57cec5SDimitry Andric return begin(std::forward<ContainerTy>(container)); 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric using std::end; 2750b57cec5SDimitry Andric 2760b57cec5SDimitry Andric template <typename ContainerTy> 2775ffd83dbSDimitry Andric decltype(auto) adl_end(ContainerTy &&container) { 2780b57cec5SDimitry Andric return end(std::forward<ContainerTy>(container)); 2790b57cec5SDimitry Andric } 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric using std::swap; 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric template <typename T> 2840b57cec5SDimitry Andric void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(), 2850b57cec5SDimitry Andric std::declval<T>()))) { 2860b57cec5SDimitry Andric swap(std::forward<T>(lhs), std::forward<T>(rhs)); 2870b57cec5SDimitry Andric } 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric } // end namespace adl_detail 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric template <typename ContainerTy> 2925ffd83dbSDimitry Andric decltype(auto) adl_begin(ContainerTy &&container) { 2930b57cec5SDimitry Andric return adl_detail::adl_begin(std::forward<ContainerTy>(container)); 2940b57cec5SDimitry Andric } 2950b57cec5SDimitry Andric 2960b57cec5SDimitry Andric template <typename ContainerTy> 2975ffd83dbSDimitry Andric decltype(auto) adl_end(ContainerTy &&container) { 2980b57cec5SDimitry Andric return adl_detail::adl_end(std::forward<ContainerTy>(container)); 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric 3010b57cec5SDimitry Andric template <typename T> 3020b57cec5SDimitry Andric void adl_swap(T &&lhs, T &&rhs) noexcept( 3030b57cec5SDimitry Andric noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) { 3040b57cec5SDimitry Andric adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs)); 3050b57cec5SDimitry Andric } 3060b57cec5SDimitry Andric 3070b57cec5SDimitry Andric /// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty. 3080b57cec5SDimitry Andric template <typename T> 3090b57cec5SDimitry Andric constexpr bool empty(const T &RangeOrContainer) { 3100b57cec5SDimitry Andric return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer); 3110b57cec5SDimitry Andric } 3120b57cec5SDimitry Andric 3135ffd83dbSDimitry Andric /// Returns true if the given container only contains a single element. 3145ffd83dbSDimitry Andric template <typename ContainerTy> bool hasSingleElement(ContainerTy &&C) { 3155ffd83dbSDimitry Andric auto B = std::begin(C), E = std::end(C); 3165ffd83dbSDimitry Andric return B != E && std::next(B) == E; 3175ffd83dbSDimitry Andric } 3185ffd83dbSDimitry Andric 319480093f4SDimitry Andric /// Return a range covering \p RangeOrContainer with the first N elements 320480093f4SDimitry Andric /// excluded. 321e8d8bef9SDimitry Andric template <typename T> auto drop_begin(T &&RangeOrContainer, size_t N = 1) { 322480093f4SDimitry Andric return make_range(std::next(adl_begin(RangeOrContainer), N), 323480093f4SDimitry Andric adl_end(RangeOrContainer)); 324480093f4SDimitry Andric } 325480093f4SDimitry Andric 3260b57cec5SDimitry Andric // mapped_iterator - This is a simple iterator adapter that causes a function to 3270b57cec5SDimitry Andric // be applied whenever operator* is invoked on the iterator. 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric template <typename ItTy, typename FuncTy, 330349cc55cSDimitry Andric typename ReferenceTy = 3310b57cec5SDimitry Andric decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))> 3320b57cec5SDimitry Andric class mapped_iterator 3330b57cec5SDimitry Andric : public iterator_adaptor_base< 3340b57cec5SDimitry Andric mapped_iterator<ItTy, FuncTy>, ItTy, 3350b57cec5SDimitry Andric typename std::iterator_traits<ItTy>::iterator_category, 336349cc55cSDimitry Andric std::remove_reference_t<ReferenceTy>, 337349cc55cSDimitry Andric typename std::iterator_traits<ItTy>::difference_type, 338349cc55cSDimitry Andric std::remove_reference_t<ReferenceTy> *, ReferenceTy> { 3390b57cec5SDimitry Andric public: 3400b57cec5SDimitry Andric mapped_iterator(ItTy U, FuncTy F) 3410b57cec5SDimitry Andric : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {} 3420b57cec5SDimitry Andric 3430b57cec5SDimitry Andric ItTy getCurrent() { return this->I; } 3440b57cec5SDimitry Andric 345349cc55cSDimitry Andric const FuncTy &getFunction() const { return F; } 346349cc55cSDimitry Andric 347349cc55cSDimitry Andric ReferenceTy operator*() const { return F(*this->I); } 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric private: 3500b57cec5SDimitry Andric FuncTy F; 3510b57cec5SDimitry Andric }; 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric // map_iterator - Provide a convenient way to create mapped_iterators, just like 3540b57cec5SDimitry Andric // make_pair is useful for creating pairs... 3550b57cec5SDimitry Andric template <class ItTy, class FuncTy> 3560b57cec5SDimitry Andric inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) { 3570b57cec5SDimitry Andric return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F)); 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric 3600b57cec5SDimitry Andric template <class ContainerTy, class FuncTy> 3615ffd83dbSDimitry Andric auto map_range(ContainerTy &&C, FuncTy F) { 3620b57cec5SDimitry Andric return make_range(map_iterator(C.begin(), F), map_iterator(C.end(), F)); 3630b57cec5SDimitry Andric } 3640b57cec5SDimitry Andric 365349cc55cSDimitry Andric /// A base type of mapped iterator, that is useful for building derived 366349cc55cSDimitry Andric /// iterators that do not need/want to store the map function (as in 367349cc55cSDimitry Andric /// mapped_iterator). These iterators must simply provide a `mapElement` method 368349cc55cSDimitry Andric /// that defines how to map a value of the iterator to the provided reference 369349cc55cSDimitry Andric /// type. 370349cc55cSDimitry Andric template <typename DerivedT, typename ItTy, typename ReferenceTy> 371349cc55cSDimitry Andric class mapped_iterator_base 372349cc55cSDimitry Andric : public iterator_adaptor_base< 373349cc55cSDimitry Andric DerivedT, ItTy, 374349cc55cSDimitry Andric typename std::iterator_traits<ItTy>::iterator_category, 375349cc55cSDimitry Andric std::remove_reference_t<ReferenceTy>, 376349cc55cSDimitry Andric typename std::iterator_traits<ItTy>::difference_type, 377349cc55cSDimitry Andric std::remove_reference_t<ReferenceTy> *, ReferenceTy> { 378349cc55cSDimitry Andric public: 379349cc55cSDimitry Andric using BaseT = mapped_iterator_base; 380349cc55cSDimitry Andric 381349cc55cSDimitry Andric mapped_iterator_base(ItTy U) 382349cc55cSDimitry Andric : mapped_iterator_base::iterator_adaptor_base(std::move(U)) {} 383349cc55cSDimitry Andric 384349cc55cSDimitry Andric ItTy getCurrent() { return this->I; } 385349cc55cSDimitry Andric 386349cc55cSDimitry Andric ReferenceTy operator*() const { 387349cc55cSDimitry Andric return static_cast<const DerivedT &>(*this).mapElement(*this->I); 388349cc55cSDimitry Andric } 389349cc55cSDimitry Andric }; 390349cc55cSDimitry Andric 3910b57cec5SDimitry Andric /// Helper to determine if type T has a member called rbegin(). 3920b57cec5SDimitry Andric template <typename Ty> class has_rbegin_impl { 3930b57cec5SDimitry Andric using yes = char[1]; 3940b57cec5SDimitry Andric using no = char[2]; 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric template <typename Inner> 3970b57cec5SDimitry Andric static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr); 3980b57cec5SDimitry Andric 3990b57cec5SDimitry Andric template <typename> 4000b57cec5SDimitry Andric static no& test(...); 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric public: 4030b57cec5SDimitry Andric static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); 4040b57cec5SDimitry Andric }; 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric /// Metafunction to determine if T& or T has a member called rbegin(). 4070b57cec5SDimitry Andric template <typename Ty> 4080b57cec5SDimitry Andric struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> { 4090b57cec5SDimitry Andric }; 4100b57cec5SDimitry Andric 4110b57cec5SDimitry Andric // Returns an iterator_range over the given container which iterates in reverse. 4120b57cec5SDimitry Andric // Note that the container must have rbegin()/rend() methods for this to work. 4130b57cec5SDimitry Andric template <typename ContainerTy> 4140b57cec5SDimitry Andric auto reverse(ContainerTy &&C, 4155ffd83dbSDimitry Andric std::enable_if_t<has_rbegin<ContainerTy>::value> * = nullptr) { 4160b57cec5SDimitry Andric return make_range(C.rbegin(), C.rend()); 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric // Returns a std::reverse_iterator wrapped around the given iterator. 4200b57cec5SDimitry Andric template <typename IteratorTy> 4210b57cec5SDimitry Andric std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) { 4220b57cec5SDimitry Andric return std::reverse_iterator<IteratorTy>(It); 4230b57cec5SDimitry Andric } 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric // Returns an iterator_range over the given container which iterates in reverse. 4260b57cec5SDimitry Andric // Note that the container must have begin()/end() methods which return 4270b57cec5SDimitry Andric // bidirectional iterators for this to work. 4280b57cec5SDimitry Andric template <typename ContainerTy> 4295ffd83dbSDimitry Andric auto reverse(ContainerTy &&C, 4305ffd83dbSDimitry Andric std::enable_if_t<!has_rbegin<ContainerTy>::value> * = nullptr) { 4310b57cec5SDimitry Andric return make_range(llvm::make_reverse_iterator(std::end(C)), 4320b57cec5SDimitry Andric llvm::make_reverse_iterator(std::begin(C))); 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric /// An iterator adaptor that filters the elements of given inner iterators. 4360b57cec5SDimitry Andric /// 4370b57cec5SDimitry Andric /// The predicate parameter should be a callable object that accepts the wrapped 4380b57cec5SDimitry Andric /// iterator's reference type and returns a bool. When incrementing or 4390b57cec5SDimitry Andric /// decrementing the iterator, it will call the predicate on each element and 4400b57cec5SDimitry Andric /// skip any where it returns false. 4410b57cec5SDimitry Andric /// 4420b57cec5SDimitry Andric /// \code 4430b57cec5SDimitry Andric /// int A[] = { 1, 2, 3, 4 }; 4440b57cec5SDimitry Andric /// auto R = make_filter_range(A, [](int N) { return N % 2 == 1; }); 4450b57cec5SDimitry Andric /// // R contains { 1, 3 }. 4460b57cec5SDimitry Andric /// \endcode 4470b57cec5SDimitry Andric /// 4480b57cec5SDimitry Andric /// Note: filter_iterator_base implements support for forward iteration. 4490b57cec5SDimitry Andric /// filter_iterator_impl exists to provide support for bidirectional iteration, 4500b57cec5SDimitry Andric /// conditional on whether the wrapped iterator supports it. 4510b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT, typename IterTag> 4520b57cec5SDimitry Andric class filter_iterator_base 4530b57cec5SDimitry Andric : public iterator_adaptor_base< 4540b57cec5SDimitry Andric filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>, 4550b57cec5SDimitry Andric WrappedIteratorT, 4560b57cec5SDimitry Andric typename std::common_type< 4570b57cec5SDimitry Andric IterTag, typename std::iterator_traits< 4580b57cec5SDimitry Andric WrappedIteratorT>::iterator_category>::type> { 459349cc55cSDimitry Andric using BaseT = typename filter_iterator_base::iterator_adaptor_base; 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric protected: 4620b57cec5SDimitry Andric WrappedIteratorT End; 4630b57cec5SDimitry Andric PredicateT Pred; 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric void findNextValid() { 4660b57cec5SDimitry Andric while (this->I != End && !Pred(*this->I)) 4670b57cec5SDimitry Andric BaseT::operator++(); 4680b57cec5SDimitry Andric } 4690b57cec5SDimitry Andric 4700b57cec5SDimitry Andric // Construct the iterator. The begin iterator needs to know where the end 4710b57cec5SDimitry Andric // is, so that it can properly stop when it gets there. The end iterator only 4720b57cec5SDimitry Andric // needs the predicate to support bidirectional iteration. 4730b57cec5SDimitry Andric filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End, 4740b57cec5SDimitry Andric PredicateT Pred) 4750b57cec5SDimitry Andric : BaseT(Begin), End(End), Pred(Pred) { 4760b57cec5SDimitry Andric findNextValid(); 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric public: 4800b57cec5SDimitry Andric using BaseT::operator++; 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric filter_iterator_base &operator++() { 4830b57cec5SDimitry Andric BaseT::operator++(); 4840b57cec5SDimitry Andric findNextValid(); 4850b57cec5SDimitry Andric return *this; 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric }; 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric /// Specialization of filter_iterator_base for forward iteration only. 4900b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT, 4910b57cec5SDimitry Andric typename IterTag = std::forward_iterator_tag> 4920b57cec5SDimitry Andric class filter_iterator_impl 4930b57cec5SDimitry Andric : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> { 4940b57cec5SDimitry Andric public: 4950b57cec5SDimitry Andric filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, 4960b57cec5SDimitry Andric PredicateT Pred) 497349cc55cSDimitry Andric : filter_iterator_impl::filter_iterator_base(Begin, End, Pred) {} 4980b57cec5SDimitry Andric }; 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric /// Specialization of filter_iterator_base for bidirectional iteration. 5010b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT> 5020b57cec5SDimitry Andric class filter_iterator_impl<WrappedIteratorT, PredicateT, 5030b57cec5SDimitry Andric std::bidirectional_iterator_tag> 5040b57cec5SDimitry Andric : public filter_iterator_base<WrappedIteratorT, PredicateT, 5050b57cec5SDimitry Andric std::bidirectional_iterator_tag> { 506349cc55cSDimitry Andric using BaseT = typename filter_iterator_impl::filter_iterator_base; 507349cc55cSDimitry Andric 5080b57cec5SDimitry Andric void findPrevValid() { 5090b57cec5SDimitry Andric while (!this->Pred(*this->I)) 5100b57cec5SDimitry Andric BaseT::operator--(); 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric public: 5140b57cec5SDimitry Andric using BaseT::operator--; 5150b57cec5SDimitry Andric 5160b57cec5SDimitry Andric filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, 5170b57cec5SDimitry Andric PredicateT Pred) 5180b57cec5SDimitry Andric : BaseT(Begin, End, Pred) {} 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric filter_iterator_impl &operator--() { 5210b57cec5SDimitry Andric BaseT::operator--(); 5220b57cec5SDimitry Andric findPrevValid(); 5230b57cec5SDimitry Andric return *this; 5240b57cec5SDimitry Andric } 5250b57cec5SDimitry Andric }; 5260b57cec5SDimitry Andric 5270b57cec5SDimitry Andric namespace detail { 5280b57cec5SDimitry Andric 5290b57cec5SDimitry Andric template <bool is_bidirectional> struct fwd_or_bidi_tag_impl { 5300b57cec5SDimitry Andric using type = std::forward_iterator_tag; 5310b57cec5SDimitry Andric }; 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric template <> struct fwd_or_bidi_tag_impl<true> { 5340b57cec5SDimitry Andric using type = std::bidirectional_iterator_tag; 5350b57cec5SDimitry Andric }; 5360b57cec5SDimitry Andric 5370b57cec5SDimitry Andric /// Helper which sets its type member to forward_iterator_tag if the category 5380b57cec5SDimitry Andric /// of \p IterT does not derive from bidirectional_iterator_tag, and to 5390b57cec5SDimitry Andric /// bidirectional_iterator_tag otherwise. 5400b57cec5SDimitry Andric template <typename IterT> struct fwd_or_bidi_tag { 5410b57cec5SDimitry Andric using type = typename fwd_or_bidi_tag_impl<std::is_base_of< 5420b57cec5SDimitry Andric std::bidirectional_iterator_tag, 5430b57cec5SDimitry Andric typename std::iterator_traits<IterT>::iterator_category>::value>::type; 5440b57cec5SDimitry Andric }; 5450b57cec5SDimitry Andric 5460b57cec5SDimitry Andric } // namespace detail 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric /// Defines filter_iterator to a suitable specialization of 5490b57cec5SDimitry Andric /// filter_iterator_impl, based on the underlying iterator's category. 5500b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT> 5510b57cec5SDimitry Andric using filter_iterator = filter_iterator_impl< 5520b57cec5SDimitry Andric WrappedIteratorT, PredicateT, 5530b57cec5SDimitry Andric typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>; 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric /// Convenience function that takes a range of elements and a predicate, 5560b57cec5SDimitry Andric /// and return a new filter_iterator range. 5570b57cec5SDimitry Andric /// 5580b57cec5SDimitry Andric /// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the 5590b57cec5SDimitry Andric /// lifetime of that temporary is not kept by the returned range object, and the 5600b57cec5SDimitry Andric /// temporary is going to be dropped on the floor after the make_iterator_range 5610b57cec5SDimitry Andric /// full expression that contains this function call. 5620b57cec5SDimitry Andric template <typename RangeT, typename PredicateT> 5630b57cec5SDimitry Andric iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>> 5640b57cec5SDimitry Andric make_filter_range(RangeT &&Range, PredicateT Pred) { 5650b57cec5SDimitry Andric using FilterIteratorT = 5660b57cec5SDimitry Andric filter_iterator<detail::IterOfRange<RangeT>, PredicateT>; 5670b57cec5SDimitry Andric return make_range( 5680b57cec5SDimitry Andric FilterIteratorT(std::begin(std::forward<RangeT>(Range)), 5690b57cec5SDimitry Andric std::end(std::forward<RangeT>(Range)), Pred), 5700b57cec5SDimitry Andric FilterIteratorT(std::end(std::forward<RangeT>(Range)), 5710b57cec5SDimitry Andric std::end(std::forward<RangeT>(Range)), Pred)); 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric /// A pseudo-iterator adaptor that is designed to implement "early increment" 5750b57cec5SDimitry Andric /// style loops. 5760b57cec5SDimitry Andric /// 5770b57cec5SDimitry Andric /// This is *not a normal iterator* and should almost never be used directly. It 5780b57cec5SDimitry Andric /// is intended primarily to be used with range based for loops and some range 5790b57cec5SDimitry Andric /// algorithms. 5800b57cec5SDimitry Andric /// 5810b57cec5SDimitry Andric /// The iterator isn't quite an `OutputIterator` or an `InputIterator` but 5820b57cec5SDimitry Andric /// somewhere between them. The constraints of these iterators are: 5830b57cec5SDimitry Andric /// 5840b57cec5SDimitry Andric /// - On construction or after being incremented, it is comparable and 5850b57cec5SDimitry Andric /// dereferencable. It is *not* incrementable. 5860b57cec5SDimitry Andric /// - After being dereferenced, it is neither comparable nor dereferencable, it 5870b57cec5SDimitry Andric /// is only incrementable. 5880b57cec5SDimitry Andric /// 5890b57cec5SDimitry Andric /// This means you can only dereference the iterator once, and you can only 5900b57cec5SDimitry Andric /// increment it once between dereferences. 5910b57cec5SDimitry Andric template <typename WrappedIteratorT> 5920b57cec5SDimitry Andric class early_inc_iterator_impl 5930b57cec5SDimitry Andric : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>, 5940b57cec5SDimitry Andric WrappedIteratorT, std::input_iterator_tag> { 595349cc55cSDimitry Andric using BaseT = typename early_inc_iterator_impl::iterator_adaptor_base; 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer; 5980b57cec5SDimitry Andric 5990b57cec5SDimitry Andric protected: 6000b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS 6010b57cec5SDimitry Andric bool IsEarlyIncremented = false; 6020b57cec5SDimitry Andric #endif 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric public: 6050b57cec5SDimitry Andric early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {} 6060b57cec5SDimitry Andric 6070b57cec5SDimitry Andric using BaseT::operator*; 608e8d8bef9SDimitry Andric decltype(*std::declval<WrappedIteratorT>()) operator*() { 6090b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS 6100b57cec5SDimitry Andric assert(!IsEarlyIncremented && "Cannot dereference twice!"); 6110b57cec5SDimitry Andric IsEarlyIncremented = true; 6120b57cec5SDimitry Andric #endif 6130b57cec5SDimitry Andric return *(this->I)++; 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric using BaseT::operator++; 6170b57cec5SDimitry Andric early_inc_iterator_impl &operator++() { 6180b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS 6190b57cec5SDimitry Andric assert(IsEarlyIncremented && "Cannot increment before dereferencing!"); 6200b57cec5SDimitry Andric IsEarlyIncremented = false; 6210b57cec5SDimitry Andric #endif 6220b57cec5SDimitry Andric return *this; 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric 625e8d8bef9SDimitry Andric friend bool operator==(const early_inc_iterator_impl &LHS, 626e8d8bef9SDimitry Andric const early_inc_iterator_impl &RHS) { 6270b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS 628e8d8bef9SDimitry Andric assert(!LHS.IsEarlyIncremented && "Cannot compare after dereferencing!"); 6290b57cec5SDimitry Andric #endif 630e8d8bef9SDimitry Andric return (const BaseT &)LHS == (const BaseT &)RHS; 6310b57cec5SDimitry Andric } 6320b57cec5SDimitry Andric }; 6330b57cec5SDimitry Andric 6340b57cec5SDimitry Andric /// Make a range that does early increment to allow mutation of the underlying 6350b57cec5SDimitry Andric /// range without disrupting iteration. 6360b57cec5SDimitry Andric /// 6370b57cec5SDimitry Andric /// The underlying iterator will be incremented immediately after it is 6380b57cec5SDimitry Andric /// dereferenced, allowing deletion of the current node or insertion of nodes to 6390b57cec5SDimitry Andric /// not disrupt iteration provided they do not invalidate the *next* iterator -- 6400b57cec5SDimitry Andric /// the current iterator can be invalidated. 6410b57cec5SDimitry Andric /// 6420b57cec5SDimitry Andric /// This requires a very exact pattern of use that is only really suitable to 6430b57cec5SDimitry Andric /// range based for loops and other range algorithms that explicitly guarantee 6440b57cec5SDimitry Andric /// to dereference exactly once each element, and to increment exactly once each 6450b57cec5SDimitry Andric /// element. 6460b57cec5SDimitry Andric template <typename RangeT> 6470b57cec5SDimitry Andric iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>> 6480b57cec5SDimitry Andric make_early_inc_range(RangeT &&Range) { 6490b57cec5SDimitry Andric using EarlyIncIteratorT = 6500b57cec5SDimitry Andric early_inc_iterator_impl<detail::IterOfRange<RangeT>>; 6510b57cec5SDimitry Andric return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))), 6520b57cec5SDimitry Andric EarlyIncIteratorT(std::end(std::forward<RangeT>(Range)))); 6530b57cec5SDimitry Andric } 6540b57cec5SDimitry Andric 6550b57cec5SDimitry Andric // forward declarations required by zip_shortest/zip_first/zip_longest 6560b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 6570b57cec5SDimitry Andric bool all_of(R &&range, UnaryPredicate P); 6580b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 6590b57cec5SDimitry Andric bool any_of(R &&range, UnaryPredicate P); 6600b57cec5SDimitry Andric 6610b57cec5SDimitry Andric namespace detail { 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric using std::declval; 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric // We have to alias this since inlining the actual type at the usage site 6660b57cec5SDimitry Andric // in the parameter list of iterator_facade_base<> below ICEs MSVC 2017. 6670b57cec5SDimitry Andric template<typename... Iters> struct ZipTupleType { 6680b57cec5SDimitry Andric using type = std::tuple<decltype(*declval<Iters>())...>; 6690b57cec5SDimitry Andric }; 6700b57cec5SDimitry Andric 6710b57cec5SDimitry Andric template <typename ZipType, typename... Iters> 6720b57cec5SDimitry Andric using zip_traits = iterator_facade_base< 6730b57cec5SDimitry Andric ZipType, typename std::common_type<std::bidirectional_iterator_tag, 6740b57cec5SDimitry Andric typename std::iterator_traits< 6750b57cec5SDimitry Andric Iters>::iterator_category...>::type, 6760b57cec5SDimitry Andric // ^ TODO: Implement random access methods. 6770b57cec5SDimitry Andric typename ZipTupleType<Iters...>::type, 6780b57cec5SDimitry Andric typename std::iterator_traits<typename std::tuple_element< 6790b57cec5SDimitry Andric 0, std::tuple<Iters...>>::type>::difference_type, 6800b57cec5SDimitry Andric // ^ FIXME: This follows boost::make_zip_iterator's assumption that all 6810b57cec5SDimitry Andric // inner iterators have the same difference_type. It would fail if, for 6820b57cec5SDimitry Andric // instance, the second field's difference_type were non-numeric while the 6830b57cec5SDimitry Andric // first is. 6840b57cec5SDimitry Andric typename ZipTupleType<Iters...>::type *, 6850b57cec5SDimitry Andric typename ZipTupleType<Iters...>::type>; 6860b57cec5SDimitry Andric 6870b57cec5SDimitry Andric template <typename ZipType, typename... Iters> 6880b57cec5SDimitry Andric struct zip_common : public zip_traits<ZipType, Iters...> { 6890b57cec5SDimitry Andric using Base = zip_traits<ZipType, Iters...>; 6900b57cec5SDimitry Andric using value_type = typename Base::value_type; 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric std::tuple<Iters...> iterators; 6930b57cec5SDimitry Andric 6940b57cec5SDimitry Andric protected: 6958bcb0991SDimitry Andric template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const { 6960b57cec5SDimitry Andric return value_type(*std::get<Ns>(iterators)...); 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 6990b57cec5SDimitry Andric template <size_t... Ns> 7008bcb0991SDimitry Andric decltype(iterators) tup_inc(std::index_sequence<Ns...>) const { 7010b57cec5SDimitry Andric return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...); 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric template <size_t... Ns> 7058bcb0991SDimitry Andric decltype(iterators) tup_dec(std::index_sequence<Ns...>) const { 7060b57cec5SDimitry Andric return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...); 7070b57cec5SDimitry Andric } 7080b57cec5SDimitry Andric 709349cc55cSDimitry Andric template <size_t... Ns> 710349cc55cSDimitry Andric bool test_all_equals(const zip_common &other, 711349cc55cSDimitry Andric std::index_sequence<Ns...>) const { 712349cc55cSDimitry Andric return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) == 713349cc55cSDimitry Andric std::get<Ns>(other.iterators)...}, 714349cc55cSDimitry Andric identity<bool>{}); 715349cc55cSDimitry Andric } 716349cc55cSDimitry Andric 7170b57cec5SDimitry Andric public: 7180b57cec5SDimitry Andric zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {} 7190b57cec5SDimitry Andric 720349cc55cSDimitry Andric value_type operator*() const { 7218bcb0991SDimitry Andric return deref(std::index_sequence_for<Iters...>{}); 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric ZipType &operator++() { 7258bcb0991SDimitry Andric iterators = tup_inc(std::index_sequence_for<Iters...>{}); 7260b57cec5SDimitry Andric return *reinterpret_cast<ZipType *>(this); 7270b57cec5SDimitry Andric } 7280b57cec5SDimitry Andric 7290b57cec5SDimitry Andric ZipType &operator--() { 7300b57cec5SDimitry Andric static_assert(Base::IsBidirectional, 7310b57cec5SDimitry Andric "All inner iterators must be at least bidirectional."); 7328bcb0991SDimitry Andric iterators = tup_dec(std::index_sequence_for<Iters...>{}); 7330b57cec5SDimitry Andric return *reinterpret_cast<ZipType *>(this); 7340b57cec5SDimitry Andric } 735349cc55cSDimitry Andric 736349cc55cSDimitry Andric /// Return true if all the iterator are matching `other`'s iterators. 737349cc55cSDimitry Andric bool all_equals(zip_common &other) { 738349cc55cSDimitry Andric return test_all_equals(other, std::index_sequence_for<Iters...>{}); 739349cc55cSDimitry Andric } 7400b57cec5SDimitry Andric }; 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric template <typename... Iters> 7430b57cec5SDimitry Andric struct zip_first : public zip_common<zip_first<Iters...>, Iters...> { 7440b57cec5SDimitry Andric using Base = zip_common<zip_first<Iters...>, Iters...>; 7450b57cec5SDimitry Andric 7460b57cec5SDimitry Andric bool operator==(const zip_first<Iters...> &other) const { 7470b57cec5SDimitry Andric return std::get<0>(this->iterators) == std::get<0>(other.iterators); 7480b57cec5SDimitry Andric } 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} 7510b57cec5SDimitry Andric }; 7520b57cec5SDimitry Andric 7530b57cec5SDimitry Andric template <typename... Iters> 7540b57cec5SDimitry Andric class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> { 7550b57cec5SDimitry Andric template <size_t... Ns> 7568bcb0991SDimitry Andric bool test(const zip_shortest<Iters...> &other, 7578bcb0991SDimitry Andric std::index_sequence<Ns...>) const { 7580b57cec5SDimitry Andric return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) != 7590b57cec5SDimitry Andric std::get<Ns>(other.iterators)...}, 7600b57cec5SDimitry Andric identity<bool>{}); 7610b57cec5SDimitry Andric } 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric public: 7640b57cec5SDimitry Andric using Base = zip_common<zip_shortest<Iters...>, Iters...>; 7650b57cec5SDimitry Andric 7660b57cec5SDimitry Andric zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {} 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric bool operator==(const zip_shortest<Iters...> &other) const { 7698bcb0991SDimitry Andric return !test(other, std::index_sequence_for<Iters...>{}); 7700b57cec5SDimitry Andric } 7710b57cec5SDimitry Andric }; 7720b57cec5SDimitry Andric 7730b57cec5SDimitry Andric template <template <typename...> class ItType, typename... Args> class zippy { 7740b57cec5SDimitry Andric public: 7750b57cec5SDimitry Andric using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>; 7760b57cec5SDimitry Andric using iterator_category = typename iterator::iterator_category; 7770b57cec5SDimitry Andric using value_type = typename iterator::value_type; 7780b57cec5SDimitry Andric using difference_type = typename iterator::difference_type; 7790b57cec5SDimitry Andric using pointer = typename iterator::pointer; 7800b57cec5SDimitry Andric using reference = typename iterator::reference; 7810b57cec5SDimitry Andric 7820b57cec5SDimitry Andric private: 7830b57cec5SDimitry Andric std::tuple<Args...> ts; 7840b57cec5SDimitry Andric 7858bcb0991SDimitry Andric template <size_t... Ns> 7868bcb0991SDimitry Andric iterator begin_impl(std::index_sequence<Ns...>) const { 7870b57cec5SDimitry Andric return iterator(std::begin(std::get<Ns>(ts))...); 7880b57cec5SDimitry Andric } 7898bcb0991SDimitry Andric template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const { 7900b57cec5SDimitry Andric return iterator(std::end(std::get<Ns>(ts))...); 7910b57cec5SDimitry Andric } 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric public: 7940b57cec5SDimitry Andric zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} 7950b57cec5SDimitry Andric 7968bcb0991SDimitry Andric iterator begin() const { 7978bcb0991SDimitry Andric return begin_impl(std::index_sequence_for<Args...>{}); 7988bcb0991SDimitry Andric } 7998bcb0991SDimitry Andric iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); } 8000b57cec5SDimitry Andric }; 8010b57cec5SDimitry Andric 8020b57cec5SDimitry Andric } // end namespace detail 8030b57cec5SDimitry Andric 8040b57cec5SDimitry Andric /// zip iterator for two or more iteratable types. 8050b57cec5SDimitry Andric template <typename T, typename U, typename... Args> 8060b57cec5SDimitry Andric detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u, 8070b57cec5SDimitry Andric Args &&... args) { 8080b57cec5SDimitry Andric return detail::zippy<detail::zip_shortest, T, U, Args...>( 8090b57cec5SDimitry Andric std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); 8100b57cec5SDimitry Andric } 8110b57cec5SDimitry Andric 8120b57cec5SDimitry Andric /// zip iterator that, for the sake of efficiency, assumes the first iteratee to 8130b57cec5SDimitry Andric /// be the shortest. 8140b57cec5SDimitry Andric template <typename T, typename U, typename... Args> 8150b57cec5SDimitry Andric detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u, 8160b57cec5SDimitry Andric Args &&... args) { 8170b57cec5SDimitry Andric return detail::zippy<detail::zip_first, T, U, Args...>( 8180b57cec5SDimitry Andric std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); 8190b57cec5SDimitry Andric } 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andric namespace detail { 8220b57cec5SDimitry Andric template <typename Iter> 8235ffd83dbSDimitry Andric Iter next_or_end(const Iter &I, const Iter &End) { 8240b57cec5SDimitry Andric if (I == End) 8250b57cec5SDimitry Andric return End; 8260b57cec5SDimitry Andric return std::next(I); 8270b57cec5SDimitry Andric } 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric template <typename Iter> 8305ffd83dbSDimitry Andric auto deref_or_none(const Iter &I, const Iter &End) -> llvm::Optional< 8315ffd83dbSDimitry Andric std::remove_const_t<std::remove_reference_t<decltype(*I)>>> { 8320b57cec5SDimitry Andric if (I == End) 8330b57cec5SDimitry Andric return None; 8340b57cec5SDimitry Andric return *I; 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric template <typename Iter> struct ZipLongestItemType { 8380b57cec5SDimitry Andric using type = 8390b57cec5SDimitry Andric llvm::Optional<typename std::remove_const<typename std::remove_reference< 8400b57cec5SDimitry Andric decltype(*std::declval<Iter>())>::type>::type>; 8410b57cec5SDimitry Andric }; 8420b57cec5SDimitry Andric 8430b57cec5SDimitry Andric template <typename... Iters> struct ZipLongestTupleType { 8440b57cec5SDimitry Andric using type = std::tuple<typename ZipLongestItemType<Iters>::type...>; 8450b57cec5SDimitry Andric }; 8460b57cec5SDimitry Andric 8470b57cec5SDimitry Andric template <typename... Iters> 8480b57cec5SDimitry Andric class zip_longest_iterator 8490b57cec5SDimitry Andric : public iterator_facade_base< 8500b57cec5SDimitry Andric zip_longest_iterator<Iters...>, 8510b57cec5SDimitry Andric typename std::common_type< 8520b57cec5SDimitry Andric std::forward_iterator_tag, 8530b57cec5SDimitry Andric typename std::iterator_traits<Iters>::iterator_category...>::type, 8540b57cec5SDimitry Andric typename ZipLongestTupleType<Iters...>::type, 8550b57cec5SDimitry Andric typename std::iterator_traits<typename std::tuple_element< 8560b57cec5SDimitry Andric 0, std::tuple<Iters...>>::type>::difference_type, 8570b57cec5SDimitry Andric typename ZipLongestTupleType<Iters...>::type *, 8580b57cec5SDimitry Andric typename ZipLongestTupleType<Iters...>::type> { 8590b57cec5SDimitry Andric public: 8600b57cec5SDimitry Andric using value_type = typename ZipLongestTupleType<Iters...>::type; 8610b57cec5SDimitry Andric 8620b57cec5SDimitry Andric private: 8630b57cec5SDimitry Andric std::tuple<Iters...> iterators; 8640b57cec5SDimitry Andric std::tuple<Iters...> end_iterators; 8650b57cec5SDimitry Andric 8660b57cec5SDimitry Andric template <size_t... Ns> 8670b57cec5SDimitry Andric bool test(const zip_longest_iterator<Iters...> &other, 8688bcb0991SDimitry Andric std::index_sequence<Ns...>) const { 8690b57cec5SDimitry Andric return llvm::any_of( 8700b57cec5SDimitry Andric std::initializer_list<bool>{std::get<Ns>(this->iterators) != 8710b57cec5SDimitry Andric std::get<Ns>(other.iterators)...}, 8720b57cec5SDimitry Andric identity<bool>{}); 8730b57cec5SDimitry Andric } 8740b57cec5SDimitry Andric 8758bcb0991SDimitry Andric template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const { 8760b57cec5SDimitry Andric return value_type( 8770b57cec5SDimitry Andric deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...); 8780b57cec5SDimitry Andric } 8790b57cec5SDimitry Andric 8800b57cec5SDimitry Andric template <size_t... Ns> 8818bcb0991SDimitry Andric decltype(iterators) tup_inc(std::index_sequence<Ns...>) const { 8820b57cec5SDimitry Andric return std::tuple<Iters...>( 8830b57cec5SDimitry Andric next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...); 8840b57cec5SDimitry Andric } 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric public: 8870b57cec5SDimitry Andric zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts) 8880b57cec5SDimitry Andric : iterators(std::forward<Iters>(ts.first)...), 8890b57cec5SDimitry Andric end_iterators(std::forward<Iters>(ts.second)...) {} 8900b57cec5SDimitry Andric 8918bcb0991SDimitry Andric value_type operator*() const { 8928bcb0991SDimitry Andric return deref(std::index_sequence_for<Iters...>{}); 8938bcb0991SDimitry Andric } 8940b57cec5SDimitry Andric 8950b57cec5SDimitry Andric zip_longest_iterator<Iters...> &operator++() { 8968bcb0991SDimitry Andric iterators = tup_inc(std::index_sequence_for<Iters...>{}); 8970b57cec5SDimitry Andric return *this; 8980b57cec5SDimitry Andric } 8990b57cec5SDimitry Andric 9000b57cec5SDimitry Andric bool operator==(const zip_longest_iterator<Iters...> &other) const { 9018bcb0991SDimitry Andric return !test(other, std::index_sequence_for<Iters...>{}); 9020b57cec5SDimitry Andric } 9030b57cec5SDimitry Andric }; 9040b57cec5SDimitry Andric 9050b57cec5SDimitry Andric template <typename... Args> class zip_longest_range { 9060b57cec5SDimitry Andric public: 9070b57cec5SDimitry Andric using iterator = 9080b57cec5SDimitry Andric zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>; 9090b57cec5SDimitry Andric using iterator_category = typename iterator::iterator_category; 9100b57cec5SDimitry Andric using value_type = typename iterator::value_type; 9110b57cec5SDimitry Andric using difference_type = typename iterator::difference_type; 9120b57cec5SDimitry Andric using pointer = typename iterator::pointer; 9130b57cec5SDimitry Andric using reference = typename iterator::reference; 9140b57cec5SDimitry Andric 9150b57cec5SDimitry Andric private: 9160b57cec5SDimitry Andric std::tuple<Args...> ts; 9170b57cec5SDimitry Andric 9188bcb0991SDimitry Andric template <size_t... Ns> 9198bcb0991SDimitry Andric iterator begin_impl(std::index_sequence<Ns...>) const { 9200b57cec5SDimitry Andric return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)), 9210b57cec5SDimitry Andric adl_end(std::get<Ns>(ts)))...); 9220b57cec5SDimitry Andric } 9230b57cec5SDimitry Andric 9248bcb0991SDimitry Andric template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const { 9250b57cec5SDimitry Andric return iterator(std::make_pair(adl_end(std::get<Ns>(ts)), 9260b57cec5SDimitry Andric adl_end(std::get<Ns>(ts)))...); 9270b57cec5SDimitry Andric } 9280b57cec5SDimitry Andric 9290b57cec5SDimitry Andric public: 9300b57cec5SDimitry Andric zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {} 9310b57cec5SDimitry Andric 9328bcb0991SDimitry Andric iterator begin() const { 9338bcb0991SDimitry Andric return begin_impl(std::index_sequence_for<Args...>{}); 9348bcb0991SDimitry Andric } 9358bcb0991SDimitry Andric iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); } 9360b57cec5SDimitry Andric }; 9370b57cec5SDimitry Andric } // namespace detail 9380b57cec5SDimitry Andric 9390b57cec5SDimitry Andric /// Iterate over two or more iterators at the same time. Iteration continues 9400b57cec5SDimitry Andric /// until all iterators reach the end. The llvm::Optional only contains a value 9410b57cec5SDimitry Andric /// if the iterator has not reached the end. 9420b57cec5SDimitry Andric template <typename T, typename U, typename... Args> 9430b57cec5SDimitry Andric detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u, 9440b57cec5SDimitry Andric Args &&... args) { 9450b57cec5SDimitry Andric return detail::zip_longest_range<T, U, Args...>( 9460b57cec5SDimitry Andric std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...); 9470b57cec5SDimitry Andric } 9480b57cec5SDimitry Andric 9490b57cec5SDimitry Andric /// Iterator wrapper that concatenates sequences together. 9500b57cec5SDimitry Andric /// 9510b57cec5SDimitry Andric /// This can concatenate different iterators, even with different types, into 9520b57cec5SDimitry Andric /// a single iterator provided the value types of all the concatenated 9530b57cec5SDimitry Andric /// iterators expose `reference` and `pointer` types that can be converted to 9540b57cec5SDimitry Andric /// `ValueT &` and `ValueT *` respectively. It doesn't support more 9550b57cec5SDimitry Andric /// interesting/customized pointer or reference types. 9560b57cec5SDimitry Andric /// 9570b57cec5SDimitry Andric /// Currently this only supports forward or higher iterator categories as 9580b57cec5SDimitry Andric /// inputs and always exposes a forward iterator interface. 9590b57cec5SDimitry Andric template <typename ValueT, typename... IterTs> 9600b57cec5SDimitry Andric class concat_iterator 9610b57cec5SDimitry Andric : public iterator_facade_base<concat_iterator<ValueT, IterTs...>, 9620b57cec5SDimitry Andric std::forward_iterator_tag, ValueT> { 9630b57cec5SDimitry Andric using BaseT = typename concat_iterator::iterator_facade_base; 9640b57cec5SDimitry Andric 9650b57cec5SDimitry Andric /// We store both the current and end iterators for each concatenated 9660b57cec5SDimitry Andric /// sequence in a tuple of pairs. 9670b57cec5SDimitry Andric /// 9680b57cec5SDimitry Andric /// Note that something like iterator_range seems nice at first here, but the 9690b57cec5SDimitry Andric /// range properties are of little benefit and end up getting in the way 9700b57cec5SDimitry Andric /// because we need to do mutation on the current iterators. 9710b57cec5SDimitry Andric std::tuple<IterTs...> Begins; 9720b57cec5SDimitry Andric std::tuple<IterTs...> Ends; 9730b57cec5SDimitry Andric 9740b57cec5SDimitry Andric /// Attempts to increment a specific iterator. 9750b57cec5SDimitry Andric /// 9760b57cec5SDimitry Andric /// Returns true if it was able to increment the iterator. Returns false if 9770b57cec5SDimitry Andric /// the iterator is already at the end iterator. 9780b57cec5SDimitry Andric template <size_t Index> bool incrementHelper() { 9790b57cec5SDimitry Andric auto &Begin = std::get<Index>(Begins); 9800b57cec5SDimitry Andric auto &End = std::get<Index>(Ends); 9810b57cec5SDimitry Andric if (Begin == End) 9820b57cec5SDimitry Andric return false; 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric ++Begin; 9850b57cec5SDimitry Andric return true; 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric /// Increments the first non-end iterator. 9890b57cec5SDimitry Andric /// 9900b57cec5SDimitry Andric /// It is an error to call this with all iterators at the end. 9918bcb0991SDimitry Andric template <size_t... Ns> void increment(std::index_sequence<Ns...>) { 9920b57cec5SDimitry Andric // Build a sequence of functions to increment each iterator if possible. 9930b57cec5SDimitry Andric bool (concat_iterator::*IncrementHelperFns[])() = { 9940b57cec5SDimitry Andric &concat_iterator::incrementHelper<Ns>...}; 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric // Loop over them, and stop as soon as we succeed at incrementing one. 9970b57cec5SDimitry Andric for (auto &IncrementHelperFn : IncrementHelperFns) 9980b57cec5SDimitry Andric if ((this->*IncrementHelperFn)()) 9990b57cec5SDimitry Andric return; 10000b57cec5SDimitry Andric 10010b57cec5SDimitry Andric llvm_unreachable("Attempted to increment an end concat iterator!"); 10020b57cec5SDimitry Andric } 10030b57cec5SDimitry Andric 10040b57cec5SDimitry Andric /// Returns null if the specified iterator is at the end. Otherwise, 10050b57cec5SDimitry Andric /// dereferences the iterator and returns the address of the resulting 10060b57cec5SDimitry Andric /// reference. 10070b57cec5SDimitry Andric template <size_t Index> ValueT *getHelper() const { 10080b57cec5SDimitry Andric auto &Begin = std::get<Index>(Begins); 10090b57cec5SDimitry Andric auto &End = std::get<Index>(Ends); 10100b57cec5SDimitry Andric if (Begin == End) 10110b57cec5SDimitry Andric return nullptr; 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric return &*Begin; 10140b57cec5SDimitry Andric } 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric /// Finds the first non-end iterator, dereferences, and returns the resulting 10170b57cec5SDimitry Andric /// reference. 10180b57cec5SDimitry Andric /// 10190b57cec5SDimitry Andric /// It is an error to call this with all iterators at the end. 10208bcb0991SDimitry Andric template <size_t... Ns> ValueT &get(std::index_sequence<Ns...>) const { 10210b57cec5SDimitry Andric // Build a sequence of functions to get from iterator if possible. 10220b57cec5SDimitry Andric ValueT *(concat_iterator::*GetHelperFns[])() const = { 10230b57cec5SDimitry Andric &concat_iterator::getHelper<Ns>...}; 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric // Loop over them, and return the first result we find. 10260b57cec5SDimitry Andric for (auto &GetHelperFn : GetHelperFns) 10270b57cec5SDimitry Andric if (ValueT *P = (this->*GetHelperFn)()) 10280b57cec5SDimitry Andric return *P; 10290b57cec5SDimitry Andric 10300b57cec5SDimitry Andric llvm_unreachable("Attempted to get a pointer from an end concat iterator!"); 10310b57cec5SDimitry Andric } 10320b57cec5SDimitry Andric 10330b57cec5SDimitry Andric public: 10345ffd83dbSDimitry Andric /// Constructs an iterator from a sequence of ranges. 10350b57cec5SDimitry Andric /// 10360b57cec5SDimitry Andric /// We need the full range to know how to switch between each of the 10370b57cec5SDimitry Andric /// iterators. 10380b57cec5SDimitry Andric template <typename... RangeTs> 10390b57cec5SDimitry Andric explicit concat_iterator(RangeTs &&... Ranges) 10400b57cec5SDimitry Andric : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {} 10410b57cec5SDimitry Andric 10420b57cec5SDimitry Andric using BaseT::operator++; 10430b57cec5SDimitry Andric 10440b57cec5SDimitry Andric concat_iterator &operator++() { 10458bcb0991SDimitry Andric increment(std::index_sequence_for<IterTs...>()); 10460b57cec5SDimitry Andric return *this; 10470b57cec5SDimitry Andric } 10480b57cec5SDimitry Andric 10498bcb0991SDimitry Andric ValueT &operator*() const { 10508bcb0991SDimitry Andric return get(std::index_sequence_for<IterTs...>()); 10518bcb0991SDimitry Andric } 10520b57cec5SDimitry Andric 10530b57cec5SDimitry Andric bool operator==(const concat_iterator &RHS) const { 10540b57cec5SDimitry Andric return Begins == RHS.Begins && Ends == RHS.Ends; 10550b57cec5SDimitry Andric } 10560b57cec5SDimitry Andric }; 10570b57cec5SDimitry Andric 10580b57cec5SDimitry Andric namespace detail { 10590b57cec5SDimitry Andric 10600b57cec5SDimitry Andric /// Helper to store a sequence of ranges being concatenated and access them. 10610b57cec5SDimitry Andric /// 10620b57cec5SDimitry Andric /// This is designed to facilitate providing actual storage when temporaries 10630b57cec5SDimitry Andric /// are passed into the constructor such that we can use it as part of range 10640b57cec5SDimitry Andric /// based for loops. 10650b57cec5SDimitry Andric template <typename ValueT, typename... RangeTs> class concat_range { 10660b57cec5SDimitry Andric public: 10670b57cec5SDimitry Andric using iterator = 10680b57cec5SDimitry Andric concat_iterator<ValueT, 10690b57cec5SDimitry Andric decltype(std::begin(std::declval<RangeTs &>()))...>; 10700b57cec5SDimitry Andric 10710b57cec5SDimitry Andric private: 10720b57cec5SDimitry Andric std::tuple<RangeTs...> Ranges; 10730b57cec5SDimitry Andric 10744824e7fdSDimitry Andric template <size_t... Ns> 10754824e7fdSDimitry Andric iterator begin_impl(std::index_sequence<Ns...>) { 10764824e7fdSDimitry Andric return iterator(std::get<Ns>(Ranges)...); 10774824e7fdSDimitry Andric } 10784824e7fdSDimitry Andric template <size_t... Ns> 10794824e7fdSDimitry Andric iterator begin_impl(std::index_sequence<Ns...>) const { 10800b57cec5SDimitry Andric return iterator(std::get<Ns>(Ranges)...); 10810b57cec5SDimitry Andric } 10828bcb0991SDimitry Andric template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) { 10830b57cec5SDimitry Andric return iterator(make_range(std::end(std::get<Ns>(Ranges)), 10840b57cec5SDimitry Andric std::end(std::get<Ns>(Ranges)))...); 10850b57cec5SDimitry Andric } 10864824e7fdSDimitry Andric template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const { 10874824e7fdSDimitry Andric return iterator(make_range(std::end(std::get<Ns>(Ranges)), 10884824e7fdSDimitry Andric std::end(std::get<Ns>(Ranges)))...); 10894824e7fdSDimitry Andric } 10900b57cec5SDimitry Andric 10910b57cec5SDimitry Andric public: 10920b57cec5SDimitry Andric concat_range(RangeTs &&... Ranges) 10930b57cec5SDimitry Andric : Ranges(std::forward<RangeTs>(Ranges)...) {} 10940b57cec5SDimitry Andric 10954824e7fdSDimitry Andric iterator begin() { 10964824e7fdSDimitry Andric return begin_impl(std::index_sequence_for<RangeTs...>{}); 10974824e7fdSDimitry Andric } 10984824e7fdSDimitry Andric iterator begin() const { 10994824e7fdSDimitry Andric return begin_impl(std::index_sequence_for<RangeTs...>{}); 11004824e7fdSDimitry Andric } 11014824e7fdSDimitry Andric iterator end() { 11024824e7fdSDimitry Andric return end_impl(std::index_sequence_for<RangeTs...>{}); 11034824e7fdSDimitry Andric } 11044824e7fdSDimitry Andric iterator end() const { 11054824e7fdSDimitry Andric return end_impl(std::index_sequence_for<RangeTs...>{}); 11064824e7fdSDimitry Andric } 11070b57cec5SDimitry Andric }; 11080b57cec5SDimitry Andric 11090b57cec5SDimitry Andric } // end namespace detail 11100b57cec5SDimitry Andric 11110b57cec5SDimitry Andric /// Concatenated range across two or more ranges. 11120b57cec5SDimitry Andric /// 11130b57cec5SDimitry Andric /// The desired value type must be explicitly specified. 11140b57cec5SDimitry Andric template <typename ValueT, typename... RangeTs> 11150b57cec5SDimitry Andric detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) { 11160b57cec5SDimitry Andric static_assert(sizeof...(RangeTs) > 1, 11170b57cec5SDimitry Andric "Need more than one range to concatenate!"); 11180b57cec5SDimitry Andric return detail::concat_range<ValueT, RangeTs...>( 11190b57cec5SDimitry Andric std::forward<RangeTs>(Ranges)...); 11200b57cec5SDimitry Andric } 11210b57cec5SDimitry Andric 11225ffd83dbSDimitry Andric /// A utility class used to implement an iterator that contains some base object 11235ffd83dbSDimitry Andric /// and an index. The iterator moves the index but keeps the base constant. 11245ffd83dbSDimitry Andric template <typename DerivedT, typename BaseT, typename T, 11255ffd83dbSDimitry Andric typename PointerT = T *, typename ReferenceT = T &> 11265ffd83dbSDimitry Andric class indexed_accessor_iterator 11275ffd83dbSDimitry Andric : public llvm::iterator_facade_base<DerivedT, 11285ffd83dbSDimitry Andric std::random_access_iterator_tag, T, 11295ffd83dbSDimitry Andric std::ptrdiff_t, PointerT, ReferenceT> { 11305ffd83dbSDimitry Andric public: 11315ffd83dbSDimitry Andric ptrdiff_t operator-(const indexed_accessor_iterator &rhs) const { 11325ffd83dbSDimitry Andric assert(base == rhs.base && "incompatible iterators"); 11335ffd83dbSDimitry Andric return index - rhs.index; 11345ffd83dbSDimitry Andric } 11355ffd83dbSDimitry Andric bool operator==(const indexed_accessor_iterator &rhs) const { 11365ffd83dbSDimitry Andric return base == rhs.base && index == rhs.index; 11375ffd83dbSDimitry Andric } 11385ffd83dbSDimitry Andric bool operator<(const indexed_accessor_iterator &rhs) const { 11395ffd83dbSDimitry Andric assert(base == rhs.base && "incompatible iterators"); 11405ffd83dbSDimitry Andric return index < rhs.index; 11415ffd83dbSDimitry Andric } 11425ffd83dbSDimitry Andric 11435ffd83dbSDimitry Andric DerivedT &operator+=(ptrdiff_t offset) { 11445ffd83dbSDimitry Andric this->index += offset; 11455ffd83dbSDimitry Andric return static_cast<DerivedT &>(*this); 11465ffd83dbSDimitry Andric } 11475ffd83dbSDimitry Andric DerivedT &operator-=(ptrdiff_t offset) { 11485ffd83dbSDimitry Andric this->index -= offset; 11495ffd83dbSDimitry Andric return static_cast<DerivedT &>(*this); 11505ffd83dbSDimitry Andric } 11515ffd83dbSDimitry Andric 11525ffd83dbSDimitry Andric /// Returns the current index of the iterator. 11535ffd83dbSDimitry Andric ptrdiff_t getIndex() const { return index; } 11545ffd83dbSDimitry Andric 11555ffd83dbSDimitry Andric /// Returns the current base of the iterator. 11565ffd83dbSDimitry Andric const BaseT &getBase() const { return base; } 11575ffd83dbSDimitry Andric 11585ffd83dbSDimitry Andric protected: 11595ffd83dbSDimitry Andric indexed_accessor_iterator(BaseT base, ptrdiff_t index) 11605ffd83dbSDimitry Andric : base(base), index(index) {} 11615ffd83dbSDimitry Andric BaseT base; 11625ffd83dbSDimitry Andric ptrdiff_t index; 11635ffd83dbSDimitry Andric }; 11645ffd83dbSDimitry Andric 11655ffd83dbSDimitry Andric namespace detail { 11665ffd83dbSDimitry Andric /// The class represents the base of a range of indexed_accessor_iterators. It 11675ffd83dbSDimitry Andric /// provides support for many different range functionalities, e.g. 11685ffd83dbSDimitry Andric /// drop_front/slice/etc.. Derived range classes must implement the following 11695ffd83dbSDimitry Andric /// static methods: 11705ffd83dbSDimitry Andric /// * ReferenceT dereference_iterator(const BaseT &base, ptrdiff_t index) 11715ffd83dbSDimitry Andric /// - Dereference an iterator pointing to the base object at the given 11725ffd83dbSDimitry Andric /// index. 11735ffd83dbSDimitry Andric /// * BaseT offset_base(const BaseT &base, ptrdiff_t index) 11745ffd83dbSDimitry Andric /// - Return a new base that is offset from the provide base by 'index' 11755ffd83dbSDimitry Andric /// elements. 11765ffd83dbSDimitry Andric template <typename DerivedT, typename BaseT, typename T, 11775ffd83dbSDimitry Andric typename PointerT = T *, typename ReferenceT = T &> 11785ffd83dbSDimitry Andric class indexed_accessor_range_base { 11795ffd83dbSDimitry Andric public: 1180349cc55cSDimitry Andric using RangeBaseT = indexed_accessor_range_base; 11815ffd83dbSDimitry Andric 11825ffd83dbSDimitry Andric /// An iterator element of this range. 11835ffd83dbSDimitry Andric class iterator : public indexed_accessor_iterator<iterator, BaseT, T, 11845ffd83dbSDimitry Andric PointerT, ReferenceT> { 11855ffd83dbSDimitry Andric public: 11865ffd83dbSDimitry Andric // Index into this iterator, invoking a static method on the derived type. 11875ffd83dbSDimitry Andric ReferenceT operator*() const { 11885ffd83dbSDimitry Andric return DerivedT::dereference_iterator(this->getBase(), this->getIndex()); 11895ffd83dbSDimitry Andric } 11905ffd83dbSDimitry Andric 11915ffd83dbSDimitry Andric private: 11925ffd83dbSDimitry Andric iterator(BaseT owner, ptrdiff_t curIndex) 1193349cc55cSDimitry Andric : iterator::indexed_accessor_iterator(owner, curIndex) {} 11945ffd83dbSDimitry Andric 11955ffd83dbSDimitry Andric /// Allow access to the constructor. 11965ffd83dbSDimitry Andric friend indexed_accessor_range_base<DerivedT, BaseT, T, PointerT, 11975ffd83dbSDimitry Andric ReferenceT>; 11985ffd83dbSDimitry Andric }; 11995ffd83dbSDimitry Andric 12005ffd83dbSDimitry Andric indexed_accessor_range_base(iterator begin, iterator end) 12015ffd83dbSDimitry Andric : base(offset_base(begin.getBase(), begin.getIndex())), 12025ffd83dbSDimitry Andric count(end.getIndex() - begin.getIndex()) {} 12035ffd83dbSDimitry Andric indexed_accessor_range_base(const iterator_range<iterator> &range) 12045ffd83dbSDimitry Andric : indexed_accessor_range_base(range.begin(), range.end()) {} 12055ffd83dbSDimitry Andric indexed_accessor_range_base(BaseT base, ptrdiff_t count) 12065ffd83dbSDimitry Andric : base(base), count(count) {} 12075ffd83dbSDimitry Andric 12085ffd83dbSDimitry Andric iterator begin() const { return iterator(base, 0); } 12095ffd83dbSDimitry Andric iterator end() const { return iterator(base, count); } 1210fe6060f1SDimitry Andric ReferenceT operator[](size_t Index) const { 1211fe6060f1SDimitry Andric assert(Index < size() && "invalid index for value range"); 1212fe6060f1SDimitry Andric return DerivedT::dereference_iterator(base, static_cast<ptrdiff_t>(Index)); 12135ffd83dbSDimitry Andric } 12145ffd83dbSDimitry Andric ReferenceT front() const { 12155ffd83dbSDimitry Andric assert(!empty() && "expected non-empty range"); 12165ffd83dbSDimitry Andric return (*this)[0]; 12175ffd83dbSDimitry Andric } 12185ffd83dbSDimitry Andric ReferenceT back() const { 12195ffd83dbSDimitry Andric assert(!empty() && "expected non-empty range"); 12205ffd83dbSDimitry Andric return (*this)[size() - 1]; 12215ffd83dbSDimitry Andric } 12225ffd83dbSDimitry Andric 12235ffd83dbSDimitry Andric /// Compare this range with another. 12245ffd83dbSDimitry Andric template <typename OtherT> bool operator==(const OtherT &other) const { 12255ffd83dbSDimitry Andric return size() == 12265ffd83dbSDimitry Andric static_cast<size_t>(std::distance(other.begin(), other.end())) && 12275ffd83dbSDimitry Andric std::equal(begin(), end(), other.begin()); 12285ffd83dbSDimitry Andric } 12295ffd83dbSDimitry Andric template <typename OtherT> bool operator!=(const OtherT &other) const { 12305ffd83dbSDimitry Andric return !(*this == other); 12315ffd83dbSDimitry Andric } 12325ffd83dbSDimitry Andric 12335ffd83dbSDimitry Andric /// Return the size of this range. 12345ffd83dbSDimitry Andric size_t size() const { return count; } 12355ffd83dbSDimitry Andric 12365ffd83dbSDimitry Andric /// Return if the range is empty. 12375ffd83dbSDimitry Andric bool empty() const { return size() == 0; } 12385ffd83dbSDimitry Andric 12395ffd83dbSDimitry Andric /// Drop the first N elements, and keep M elements. 12405ffd83dbSDimitry Andric DerivedT slice(size_t n, size_t m) const { 12415ffd83dbSDimitry Andric assert(n + m <= size() && "invalid size specifiers"); 12425ffd83dbSDimitry Andric return DerivedT(offset_base(base, n), m); 12435ffd83dbSDimitry Andric } 12445ffd83dbSDimitry Andric 12455ffd83dbSDimitry Andric /// Drop the first n elements. 12465ffd83dbSDimitry Andric DerivedT drop_front(size_t n = 1) const { 12475ffd83dbSDimitry Andric assert(size() >= n && "Dropping more elements than exist"); 12485ffd83dbSDimitry Andric return slice(n, size() - n); 12495ffd83dbSDimitry Andric } 12505ffd83dbSDimitry Andric /// Drop the last n elements. 12515ffd83dbSDimitry Andric DerivedT drop_back(size_t n = 1) const { 12525ffd83dbSDimitry Andric assert(size() >= n && "Dropping more elements than exist"); 12535ffd83dbSDimitry Andric return DerivedT(base, size() - n); 12545ffd83dbSDimitry Andric } 12555ffd83dbSDimitry Andric 12565ffd83dbSDimitry Andric /// Take the first n elements. 12575ffd83dbSDimitry Andric DerivedT take_front(size_t n = 1) const { 12585ffd83dbSDimitry Andric return n < size() ? drop_back(size() - n) 12595ffd83dbSDimitry Andric : static_cast<const DerivedT &>(*this); 12605ffd83dbSDimitry Andric } 12615ffd83dbSDimitry Andric 12625ffd83dbSDimitry Andric /// Take the last n elements. 12635ffd83dbSDimitry Andric DerivedT take_back(size_t n = 1) const { 12645ffd83dbSDimitry Andric return n < size() ? drop_front(size() - n) 12655ffd83dbSDimitry Andric : static_cast<const DerivedT &>(*this); 12665ffd83dbSDimitry Andric } 12675ffd83dbSDimitry Andric 12685ffd83dbSDimitry Andric /// Allow conversion to any type accepting an iterator_range. 12695ffd83dbSDimitry Andric template <typename RangeT, typename = std::enable_if_t<std::is_constructible< 12705ffd83dbSDimitry Andric RangeT, iterator_range<iterator>>::value>> 12715ffd83dbSDimitry Andric operator RangeT() const { 12725ffd83dbSDimitry Andric return RangeT(iterator_range<iterator>(*this)); 12735ffd83dbSDimitry Andric } 12745ffd83dbSDimitry Andric 12755ffd83dbSDimitry Andric /// Returns the base of this range. 12765ffd83dbSDimitry Andric const BaseT &getBase() const { return base; } 12775ffd83dbSDimitry Andric 12785ffd83dbSDimitry Andric private: 12795ffd83dbSDimitry Andric /// Offset the given base by the given amount. 12805ffd83dbSDimitry Andric static BaseT offset_base(const BaseT &base, size_t n) { 12815ffd83dbSDimitry Andric return n == 0 ? base : DerivedT::offset_base(base, n); 12825ffd83dbSDimitry Andric } 12835ffd83dbSDimitry Andric 12845ffd83dbSDimitry Andric protected: 12855ffd83dbSDimitry Andric indexed_accessor_range_base(const indexed_accessor_range_base &) = default; 12865ffd83dbSDimitry Andric indexed_accessor_range_base(indexed_accessor_range_base &&) = default; 12875ffd83dbSDimitry Andric indexed_accessor_range_base & 12885ffd83dbSDimitry Andric operator=(const indexed_accessor_range_base &) = default; 12895ffd83dbSDimitry Andric 12905ffd83dbSDimitry Andric /// The base that owns the provided range of values. 12915ffd83dbSDimitry Andric BaseT base; 12925ffd83dbSDimitry Andric /// The size from the owning range. 12935ffd83dbSDimitry Andric ptrdiff_t count; 12945ffd83dbSDimitry Andric }; 12955ffd83dbSDimitry Andric } // end namespace detail 12965ffd83dbSDimitry Andric 12975ffd83dbSDimitry Andric /// This class provides an implementation of a range of 12985ffd83dbSDimitry Andric /// indexed_accessor_iterators where the base is not indexable. Ranges with 12995ffd83dbSDimitry Andric /// bases that are offsetable should derive from indexed_accessor_range_base 13005ffd83dbSDimitry Andric /// instead. Derived range classes are expected to implement the following 13015ffd83dbSDimitry Andric /// static method: 13025ffd83dbSDimitry Andric /// * ReferenceT dereference(const BaseT &base, ptrdiff_t index) 13035ffd83dbSDimitry Andric /// - Dereference an iterator pointing to a parent base at the given index. 13045ffd83dbSDimitry Andric template <typename DerivedT, typename BaseT, typename T, 13055ffd83dbSDimitry Andric typename PointerT = T *, typename ReferenceT = T &> 13065ffd83dbSDimitry Andric class indexed_accessor_range 13075ffd83dbSDimitry Andric : public detail::indexed_accessor_range_base< 13085ffd83dbSDimitry Andric DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT> { 13095ffd83dbSDimitry Andric public: 13105ffd83dbSDimitry Andric indexed_accessor_range(BaseT base, ptrdiff_t startIndex, ptrdiff_t count) 13115ffd83dbSDimitry Andric : detail::indexed_accessor_range_base< 13125ffd83dbSDimitry Andric DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT>( 13135ffd83dbSDimitry Andric std::make_pair(base, startIndex), count) {} 13145ffd83dbSDimitry Andric using detail::indexed_accessor_range_base< 13155ffd83dbSDimitry Andric DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, 13165ffd83dbSDimitry Andric ReferenceT>::indexed_accessor_range_base; 13175ffd83dbSDimitry Andric 13185ffd83dbSDimitry Andric /// Returns the current base of the range. 13195ffd83dbSDimitry Andric const BaseT &getBase() const { return this->base.first; } 13205ffd83dbSDimitry Andric 13215ffd83dbSDimitry Andric /// Returns the current start index of the range. 13225ffd83dbSDimitry Andric ptrdiff_t getStartIndex() const { return this->base.second; } 13235ffd83dbSDimitry Andric 13245ffd83dbSDimitry Andric /// See `detail::indexed_accessor_range_base` for details. 13255ffd83dbSDimitry Andric static std::pair<BaseT, ptrdiff_t> 13265ffd83dbSDimitry Andric offset_base(const std::pair<BaseT, ptrdiff_t> &base, ptrdiff_t index) { 13275ffd83dbSDimitry Andric // We encode the internal base as a pair of the derived base and a start 13285ffd83dbSDimitry Andric // index into the derived base. 13295ffd83dbSDimitry Andric return std::make_pair(base.first, base.second + index); 13305ffd83dbSDimitry Andric } 13315ffd83dbSDimitry Andric /// See `detail::indexed_accessor_range_base` for details. 13325ffd83dbSDimitry Andric static ReferenceT 13335ffd83dbSDimitry Andric dereference_iterator(const std::pair<BaseT, ptrdiff_t> &base, 13345ffd83dbSDimitry Andric ptrdiff_t index) { 13355ffd83dbSDimitry Andric return DerivedT::dereference(base.first, base.second + index); 13365ffd83dbSDimitry Andric } 13375ffd83dbSDimitry Andric }; 13385ffd83dbSDimitry Andric 1339349cc55cSDimitry Andric namespace detail { 1340349cc55cSDimitry Andric /// Return a reference to the first or second member of a reference. Otherwise, 1341349cc55cSDimitry Andric /// return a copy of the member of a temporary. 1342349cc55cSDimitry Andric /// 1343349cc55cSDimitry Andric /// When passing a range whose iterators return values instead of references, 1344349cc55cSDimitry Andric /// the reference must be dropped from `decltype((elt.first))`, which will 1345349cc55cSDimitry Andric /// always be a reference, to avoid returning a reference to a temporary. 1346349cc55cSDimitry Andric template <typename EltTy, typename FirstTy> class first_or_second_type { 1347349cc55cSDimitry Andric public: 1348349cc55cSDimitry Andric using type = 1349349cc55cSDimitry Andric typename std::conditional_t<std::is_reference<EltTy>::value, FirstTy, 1350349cc55cSDimitry Andric std::remove_reference_t<FirstTy>>; 1351349cc55cSDimitry Andric }; 1352349cc55cSDimitry Andric } // end namespace detail 1353349cc55cSDimitry Andric 1354e8d8bef9SDimitry Andric /// Given a container of pairs, return a range over the first elements. 1355e8d8bef9SDimitry Andric template <typename ContainerTy> auto make_first_range(ContainerTy &&c) { 1356349cc55cSDimitry Andric using EltTy = decltype((*std::begin(c))); 1357349cc55cSDimitry Andric return llvm::map_range(std::forward<ContainerTy>(c), 1358349cc55cSDimitry Andric [](EltTy elt) -> typename detail::first_or_second_type< 1359349cc55cSDimitry Andric EltTy, decltype((elt.first))>::type { 1360e8d8bef9SDimitry Andric return elt.first; 1361e8d8bef9SDimitry Andric }); 1362e8d8bef9SDimitry Andric } 1363e8d8bef9SDimitry Andric 13645ffd83dbSDimitry Andric /// Given a container of pairs, return a range over the second elements. 13655ffd83dbSDimitry Andric template <typename ContainerTy> auto make_second_range(ContainerTy &&c) { 1366349cc55cSDimitry Andric using EltTy = decltype((*std::begin(c))); 13675ffd83dbSDimitry Andric return llvm::map_range( 13685ffd83dbSDimitry Andric std::forward<ContainerTy>(c), 1369349cc55cSDimitry Andric [](EltTy elt) -> 1370349cc55cSDimitry Andric typename detail::first_or_second_type<EltTy, 1371349cc55cSDimitry Andric decltype((elt.second))>::type { 13725ffd83dbSDimitry Andric return elt.second; 13735ffd83dbSDimitry Andric }); 13745ffd83dbSDimitry Andric } 13755ffd83dbSDimitry Andric 13760b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13770b57cec5SDimitry Andric // Extra additions to <utility> 13780b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 13790b57cec5SDimitry Andric 13800b57cec5SDimitry Andric /// Function object to check whether the first component of a std::pair 13810b57cec5SDimitry Andric /// compares less than the first component of another std::pair. 13820b57cec5SDimitry Andric struct less_first { 13830b57cec5SDimitry Andric template <typename T> bool operator()(const T &lhs, const T &rhs) const { 1384349cc55cSDimitry Andric return std::less<>()(lhs.first, rhs.first); 13850b57cec5SDimitry Andric } 13860b57cec5SDimitry Andric }; 13870b57cec5SDimitry Andric 13880b57cec5SDimitry Andric /// Function object to check whether the second component of a std::pair 13890b57cec5SDimitry Andric /// compares less than the second component of another std::pair. 13900b57cec5SDimitry Andric struct less_second { 13910b57cec5SDimitry Andric template <typename T> bool operator()(const T &lhs, const T &rhs) const { 1392349cc55cSDimitry Andric return std::less<>()(lhs.second, rhs.second); 13930b57cec5SDimitry Andric } 13940b57cec5SDimitry Andric }; 13950b57cec5SDimitry Andric 13960b57cec5SDimitry Andric /// \brief Function object to apply a binary function to the first component of 13970b57cec5SDimitry Andric /// a std::pair. 13980b57cec5SDimitry Andric template<typename FuncTy> 13990b57cec5SDimitry Andric struct on_first { 14000b57cec5SDimitry Andric FuncTy func; 14010b57cec5SDimitry Andric 14020b57cec5SDimitry Andric template <typename T> 14035ffd83dbSDimitry Andric decltype(auto) operator()(const T &lhs, const T &rhs) const { 14040b57cec5SDimitry Andric return func(lhs.first, rhs.first); 14050b57cec5SDimitry Andric } 14060b57cec5SDimitry Andric }; 14070b57cec5SDimitry Andric 14080b57cec5SDimitry Andric /// Utility type to build an inheritance chain that makes it easy to rank 14090b57cec5SDimitry Andric /// overload candidates. 14100b57cec5SDimitry Andric template <int N> struct rank : rank<N - 1> {}; 14110b57cec5SDimitry Andric template <> struct rank<0> {}; 14120b57cec5SDimitry Andric 14130b57cec5SDimitry Andric /// traits class for checking whether type T is one of any of the given 14140b57cec5SDimitry Andric /// types in the variadic list. 1415fe6060f1SDimitry Andric template <typename T, typename... Ts> 1416fe6060f1SDimitry Andric using is_one_of = disjunction<std::is_same<T, Ts>...>; 14170b57cec5SDimitry Andric 14180b57cec5SDimitry Andric /// traits class for checking whether type T is a base class for all 14190b57cec5SDimitry Andric /// the given types in the variadic list. 1420fe6060f1SDimitry Andric template <typename T, typename... Ts> 1421fe6060f1SDimitry Andric using are_base_of = conjunction<std::is_base_of<T, Ts>...>; 1422fe6060f1SDimitry Andric 1423fe6060f1SDimitry Andric namespace detail { 1424fe6060f1SDimitry Andric template <typename... Ts> struct Visitor; 1425fe6060f1SDimitry Andric 1426fe6060f1SDimitry Andric template <typename HeadT, typename... TailTs> 1427fe6060f1SDimitry Andric struct Visitor<HeadT, TailTs...> : remove_cvref_t<HeadT>, Visitor<TailTs...> { 1428fe6060f1SDimitry Andric explicit constexpr Visitor(HeadT &&Head, TailTs &&...Tail) 1429fe6060f1SDimitry Andric : remove_cvref_t<HeadT>(std::forward<HeadT>(Head)), 1430fe6060f1SDimitry Andric Visitor<TailTs...>(std::forward<TailTs>(Tail)...) {} 1431fe6060f1SDimitry Andric using remove_cvref_t<HeadT>::operator(); 1432fe6060f1SDimitry Andric using Visitor<TailTs...>::operator(); 14330b57cec5SDimitry Andric }; 14340b57cec5SDimitry Andric 1435fe6060f1SDimitry Andric template <typename HeadT> struct Visitor<HeadT> : remove_cvref_t<HeadT> { 1436fe6060f1SDimitry Andric explicit constexpr Visitor(HeadT &&Head) 1437fe6060f1SDimitry Andric : remove_cvref_t<HeadT>(std::forward<HeadT>(Head)) {} 1438fe6060f1SDimitry Andric using remove_cvref_t<HeadT>::operator(); 14390b57cec5SDimitry Andric }; 1440fe6060f1SDimitry Andric } // namespace detail 1441fe6060f1SDimitry Andric 1442fe6060f1SDimitry Andric /// Returns an opaquely-typed Callable object whose operator() overload set is 1443fe6060f1SDimitry Andric /// the sum of the operator() overload sets of each CallableT in CallableTs. 1444fe6060f1SDimitry Andric /// 1445fe6060f1SDimitry Andric /// The type of the returned object derives from each CallableT in CallableTs. 1446fe6060f1SDimitry Andric /// The returned object is constructed by invoking the appropriate copy or move 1447fe6060f1SDimitry Andric /// constructor of each CallableT, as selected by overload resolution on the 1448fe6060f1SDimitry Andric /// corresponding argument to makeVisitor. 1449fe6060f1SDimitry Andric /// 1450fe6060f1SDimitry Andric /// Example: 1451fe6060f1SDimitry Andric /// 1452fe6060f1SDimitry Andric /// \code 1453fe6060f1SDimitry Andric /// auto visitor = makeVisitor([](auto) { return "unhandled type"; }, 1454fe6060f1SDimitry Andric /// [](int i) { return "int"; }, 1455fe6060f1SDimitry Andric /// [](std::string s) { return "str"; }); 1456fe6060f1SDimitry Andric /// auto a = visitor(42); // `a` is now "int". 1457fe6060f1SDimitry Andric /// auto b = visitor("foo"); // `b` is now "str". 1458fe6060f1SDimitry Andric /// auto c = visitor(3.14f); // `c` is now "unhandled type". 1459fe6060f1SDimitry Andric /// \endcode 1460fe6060f1SDimitry Andric /// 1461fe6060f1SDimitry Andric /// Example of making a visitor with a lambda which captures a move-only type: 1462fe6060f1SDimitry Andric /// 1463fe6060f1SDimitry Andric /// \code 1464fe6060f1SDimitry Andric /// std::unique_ptr<FooHandler> FH = /* ... */; 1465fe6060f1SDimitry Andric /// auto visitor = makeVisitor( 1466fe6060f1SDimitry Andric /// [FH{std::move(FH)}](Foo F) { return FH->handle(F); }, 1467fe6060f1SDimitry Andric /// [](int i) { return i; }, 1468fe6060f1SDimitry Andric /// [](std::string s) { return atoi(s); }); 1469fe6060f1SDimitry Andric /// \endcode 1470fe6060f1SDimitry Andric template <typename... CallableTs> 1471fe6060f1SDimitry Andric constexpr decltype(auto) makeVisitor(CallableTs &&...Callables) { 1472fe6060f1SDimitry Andric return detail::Visitor<CallableTs...>(std::forward<CallableTs>(Callables)...); 1473fe6060f1SDimitry Andric } 14740b57cec5SDimitry Andric 14750b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14760b57cec5SDimitry Andric // Extra additions for arrays 14770b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 14780b57cec5SDimitry Andric 14795ffd83dbSDimitry Andric // We have a copy here so that LLVM behaves the same when using different 14805ffd83dbSDimitry Andric // standard libraries. 14815ffd83dbSDimitry Andric template <class Iterator, class RNG> 14825ffd83dbSDimitry Andric void shuffle(Iterator first, Iterator last, RNG &&g) { 14835ffd83dbSDimitry Andric // It would be better to use a std::uniform_int_distribution, 14845ffd83dbSDimitry Andric // but that would be stdlib dependent. 1485fe6060f1SDimitry Andric typedef 1486fe6060f1SDimitry Andric typename std::iterator_traits<Iterator>::difference_type difference_type; 1487fe6060f1SDimitry Andric for (auto size = last - first; size > 1; ++first, (void)--size) { 1488fe6060f1SDimitry Andric difference_type offset = g() % size; 1489fe6060f1SDimitry Andric // Avoid self-assignment due to incorrect assertions in libstdc++ 1490fe6060f1SDimitry Andric // containers (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85828). 1491fe6060f1SDimitry Andric if (offset != difference_type(0)) 1492fe6060f1SDimitry Andric std::iter_swap(first, first + offset); 1493fe6060f1SDimitry Andric } 14945ffd83dbSDimitry Andric } 14955ffd83dbSDimitry Andric 14960b57cec5SDimitry Andric /// Find the length of an array. 14970b57cec5SDimitry Andric template <class T, std::size_t N> 14980b57cec5SDimitry Andric constexpr inline size_t array_lengthof(T (&)[N]) { 14990b57cec5SDimitry Andric return N; 15000b57cec5SDimitry Andric } 15010b57cec5SDimitry Andric 15020b57cec5SDimitry Andric /// Adapt std::less<T> for array_pod_sort. 15030b57cec5SDimitry Andric template<typename T> 15040b57cec5SDimitry Andric inline int array_pod_sort_comparator(const void *P1, const void *P2) { 15050b57cec5SDimitry Andric if (std::less<T>()(*reinterpret_cast<const T*>(P1), 15060b57cec5SDimitry Andric *reinterpret_cast<const T*>(P2))) 15070b57cec5SDimitry Andric return -1; 15080b57cec5SDimitry Andric if (std::less<T>()(*reinterpret_cast<const T*>(P2), 15090b57cec5SDimitry Andric *reinterpret_cast<const T*>(P1))) 15100b57cec5SDimitry Andric return 1; 15110b57cec5SDimitry Andric return 0; 15120b57cec5SDimitry Andric } 15130b57cec5SDimitry Andric 15140b57cec5SDimitry Andric /// get_array_pod_sort_comparator - This is an internal helper function used to 15150b57cec5SDimitry Andric /// get type deduction of T right. 15160b57cec5SDimitry Andric template<typename T> 15170b57cec5SDimitry Andric inline int (*get_array_pod_sort_comparator(const T &)) 15180b57cec5SDimitry Andric (const void*, const void*) { 15190b57cec5SDimitry Andric return array_pod_sort_comparator<T>; 15200b57cec5SDimitry Andric } 15210b57cec5SDimitry Andric 1522480093f4SDimitry Andric #ifdef EXPENSIVE_CHECKS 1523480093f4SDimitry Andric namespace detail { 1524480093f4SDimitry Andric 1525480093f4SDimitry Andric inline unsigned presortShuffleEntropy() { 1526480093f4SDimitry Andric static unsigned Result(std::random_device{}()); 1527480093f4SDimitry Andric return Result; 1528480093f4SDimitry Andric } 1529480093f4SDimitry Andric 1530480093f4SDimitry Andric template <class IteratorTy> 1531480093f4SDimitry Andric inline void presortShuffle(IteratorTy Start, IteratorTy End) { 1532480093f4SDimitry Andric std::mt19937 Generator(presortShuffleEntropy()); 1533fe6060f1SDimitry Andric llvm::shuffle(Start, End, Generator); 1534480093f4SDimitry Andric } 1535480093f4SDimitry Andric 1536480093f4SDimitry Andric } // end namespace detail 1537480093f4SDimitry Andric #endif 1538480093f4SDimitry Andric 15390b57cec5SDimitry Andric /// array_pod_sort - This sorts an array with the specified start and end 15400b57cec5SDimitry Andric /// extent. This is just like std::sort, except that it calls qsort instead of 15410b57cec5SDimitry Andric /// using an inlined template. qsort is slightly slower than std::sort, but 15420b57cec5SDimitry Andric /// most sorts are not performance critical in LLVM and std::sort has to be 15430b57cec5SDimitry Andric /// template instantiated for each type, leading to significant measured code 15440b57cec5SDimitry Andric /// bloat. This function should generally be used instead of std::sort where 15450b57cec5SDimitry Andric /// possible. 15460b57cec5SDimitry Andric /// 15470b57cec5SDimitry Andric /// This function assumes that you have simple POD-like types that can be 15480b57cec5SDimitry Andric /// compared with std::less and can be moved with memcpy. If this isn't true, 15490b57cec5SDimitry Andric /// you should use std::sort. 15500b57cec5SDimitry Andric /// 15510b57cec5SDimitry Andric /// NOTE: If qsort_r were portable, we could allow a custom comparator and 15520b57cec5SDimitry Andric /// default to std::less. 15530b57cec5SDimitry Andric template<class IteratorTy> 15540b57cec5SDimitry Andric inline void array_pod_sort(IteratorTy Start, IteratorTy End) { 15550b57cec5SDimitry Andric // Don't inefficiently call qsort with one element or trigger undefined 15560b57cec5SDimitry Andric // behavior with an empty sequence. 15570b57cec5SDimitry Andric auto NElts = End - Start; 15580b57cec5SDimitry Andric if (NElts <= 1) return; 15590b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 1560480093f4SDimitry Andric detail::presortShuffle<IteratorTy>(Start, End); 15610b57cec5SDimitry Andric #endif 15620b57cec5SDimitry Andric qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start)); 15630b57cec5SDimitry Andric } 15640b57cec5SDimitry Andric 15650b57cec5SDimitry Andric template <class IteratorTy> 15660b57cec5SDimitry Andric inline void array_pod_sort( 15670b57cec5SDimitry Andric IteratorTy Start, IteratorTy End, 15680b57cec5SDimitry Andric int (*Compare)( 15690b57cec5SDimitry Andric const typename std::iterator_traits<IteratorTy>::value_type *, 15700b57cec5SDimitry Andric const typename std::iterator_traits<IteratorTy>::value_type *)) { 15710b57cec5SDimitry Andric // Don't inefficiently call qsort with one element or trigger undefined 15720b57cec5SDimitry Andric // behavior with an empty sequence. 15730b57cec5SDimitry Andric auto NElts = End - Start; 15740b57cec5SDimitry Andric if (NElts <= 1) return; 15750b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 1576480093f4SDimitry Andric detail::presortShuffle<IteratorTy>(Start, End); 15770b57cec5SDimitry Andric #endif 15780b57cec5SDimitry Andric qsort(&*Start, NElts, sizeof(*Start), 15790b57cec5SDimitry Andric reinterpret_cast<int (*)(const void *, const void *)>(Compare)); 15800b57cec5SDimitry Andric } 15810b57cec5SDimitry Andric 15825ffd83dbSDimitry Andric namespace detail { 15835ffd83dbSDimitry Andric template <typename T> 15845ffd83dbSDimitry Andric // We can use qsort if the iterator type is a pointer and the underlying value 15855ffd83dbSDimitry Andric // is trivially copyable. 15865ffd83dbSDimitry Andric using sort_trivially_copyable = conjunction< 15875ffd83dbSDimitry Andric std::is_pointer<T>, 1588e8d8bef9SDimitry Andric std::is_trivially_copyable<typename std::iterator_traits<T>::value_type>>; 15895ffd83dbSDimitry Andric } // namespace detail 15905ffd83dbSDimitry Andric 15910b57cec5SDimitry Andric // Provide wrappers to std::sort which shuffle the elements before sorting 15920b57cec5SDimitry Andric // to help uncover non-deterministic behavior (PR35135). 15935ffd83dbSDimitry Andric template <typename IteratorTy, 15945ffd83dbSDimitry Andric std::enable_if_t<!detail::sort_trivially_copyable<IteratorTy>::value, 15955ffd83dbSDimitry Andric int> = 0> 15960b57cec5SDimitry Andric inline void sort(IteratorTy Start, IteratorTy End) { 15970b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 1598480093f4SDimitry Andric detail::presortShuffle<IteratorTy>(Start, End); 15990b57cec5SDimitry Andric #endif 16000b57cec5SDimitry Andric std::sort(Start, End); 16010b57cec5SDimitry Andric } 16020b57cec5SDimitry Andric 16035ffd83dbSDimitry Andric // Forward trivially copyable types to array_pod_sort. This avoids a large 16045ffd83dbSDimitry Andric // amount of code bloat for a minor performance hit. 16055ffd83dbSDimitry Andric template <typename IteratorTy, 16065ffd83dbSDimitry Andric std::enable_if_t<detail::sort_trivially_copyable<IteratorTy>::value, 16075ffd83dbSDimitry Andric int> = 0> 16085ffd83dbSDimitry Andric inline void sort(IteratorTy Start, IteratorTy End) { 16095ffd83dbSDimitry Andric array_pod_sort(Start, End); 16105ffd83dbSDimitry Andric } 16115ffd83dbSDimitry Andric 16120b57cec5SDimitry Andric template <typename Container> inline void sort(Container &&C) { 16130b57cec5SDimitry Andric llvm::sort(adl_begin(C), adl_end(C)); 16140b57cec5SDimitry Andric } 16150b57cec5SDimitry Andric 16160b57cec5SDimitry Andric template <typename IteratorTy, typename Compare> 16170b57cec5SDimitry Andric inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) { 16180b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS 1619480093f4SDimitry Andric detail::presortShuffle<IteratorTy>(Start, End); 16200b57cec5SDimitry Andric #endif 16210b57cec5SDimitry Andric std::sort(Start, End, Comp); 16220b57cec5SDimitry Andric } 16230b57cec5SDimitry Andric 16240b57cec5SDimitry Andric template <typename Container, typename Compare> 16250b57cec5SDimitry Andric inline void sort(Container &&C, Compare Comp) { 16260b57cec5SDimitry Andric llvm::sort(adl_begin(C), adl_end(C), Comp); 16270b57cec5SDimitry Andric } 16280b57cec5SDimitry Andric 16290b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 16300b57cec5SDimitry Andric // Extra additions to <algorithm> 16310b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 16320b57cec5SDimitry Andric 16330b57cec5SDimitry Andric /// Get the size of a range. This is a wrapper function around std::distance 16340b57cec5SDimitry Andric /// which is only enabled when the operation is O(1). 16350b57cec5SDimitry Andric template <typename R> 16365ffd83dbSDimitry Andric auto size(R &&Range, 1637e8d8bef9SDimitry Andric std::enable_if_t< 1638e8d8bef9SDimitry Andric std::is_base_of<std::random_access_iterator_tag, 1639e8d8bef9SDimitry Andric typename std::iterator_traits<decltype( 1640e8d8bef9SDimitry Andric Range.begin())>::iterator_category>::value, 16415ffd83dbSDimitry Andric void> * = nullptr) { 16420b57cec5SDimitry Andric return std::distance(Range.begin(), Range.end()); 16430b57cec5SDimitry Andric } 16440b57cec5SDimitry Andric 16450b57cec5SDimitry Andric /// Provide wrappers to std::for_each which take ranges instead of having to 16460b57cec5SDimitry Andric /// pass begin/end explicitly. 1647e8d8bef9SDimitry Andric template <typename R, typename UnaryFunction> 1648e8d8bef9SDimitry Andric UnaryFunction for_each(R &&Range, UnaryFunction F) { 1649e8d8bef9SDimitry Andric return std::for_each(adl_begin(Range), adl_end(Range), F); 16500b57cec5SDimitry Andric } 16510b57cec5SDimitry Andric 16520b57cec5SDimitry Andric /// Provide wrappers to std::all_of which take ranges instead of having to pass 16530b57cec5SDimitry Andric /// begin/end explicitly. 16540b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 16550b57cec5SDimitry Andric bool all_of(R &&Range, UnaryPredicate P) { 16560b57cec5SDimitry Andric return std::all_of(adl_begin(Range), adl_end(Range), P); 16570b57cec5SDimitry Andric } 16580b57cec5SDimitry Andric 16590b57cec5SDimitry Andric /// Provide wrappers to std::any_of which take ranges instead of having to pass 16600b57cec5SDimitry Andric /// begin/end explicitly. 16610b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 16620b57cec5SDimitry Andric bool any_of(R &&Range, UnaryPredicate P) { 16630b57cec5SDimitry Andric return std::any_of(adl_begin(Range), adl_end(Range), P); 16640b57cec5SDimitry Andric } 16650b57cec5SDimitry Andric 16660b57cec5SDimitry Andric /// Provide wrappers to std::none_of which take ranges instead of having to pass 16670b57cec5SDimitry Andric /// begin/end explicitly. 16680b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 16690b57cec5SDimitry Andric bool none_of(R &&Range, UnaryPredicate P) { 16700b57cec5SDimitry Andric return std::none_of(adl_begin(Range), adl_end(Range), P); 16710b57cec5SDimitry Andric } 16720b57cec5SDimitry Andric 16730b57cec5SDimitry Andric /// Provide wrappers to std::find which take ranges instead of having to pass 16740b57cec5SDimitry Andric /// begin/end explicitly. 16755ffd83dbSDimitry Andric template <typename R, typename T> auto find(R &&Range, const T &Val) { 16760b57cec5SDimitry Andric return std::find(adl_begin(Range), adl_end(Range), Val); 16770b57cec5SDimitry Andric } 16780b57cec5SDimitry Andric 16790b57cec5SDimitry Andric /// Provide wrappers to std::find_if which take ranges instead of having to pass 16800b57cec5SDimitry Andric /// begin/end explicitly. 16810b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 16825ffd83dbSDimitry Andric auto find_if(R &&Range, UnaryPredicate P) { 16830b57cec5SDimitry Andric return std::find_if(adl_begin(Range), adl_end(Range), P); 16840b57cec5SDimitry Andric } 16850b57cec5SDimitry Andric 16860b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 16875ffd83dbSDimitry Andric auto find_if_not(R &&Range, UnaryPredicate P) { 16880b57cec5SDimitry Andric return std::find_if_not(adl_begin(Range), adl_end(Range), P); 16890b57cec5SDimitry Andric } 16900b57cec5SDimitry Andric 16910b57cec5SDimitry Andric /// Provide wrappers to std::remove_if which take ranges instead of having to 16920b57cec5SDimitry Andric /// pass begin/end explicitly. 16930b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 16945ffd83dbSDimitry Andric auto remove_if(R &&Range, UnaryPredicate P) { 16950b57cec5SDimitry Andric return std::remove_if(adl_begin(Range), adl_end(Range), P); 16960b57cec5SDimitry Andric } 16970b57cec5SDimitry Andric 16980b57cec5SDimitry Andric /// Provide wrappers to std::copy_if which take ranges instead of having to 16990b57cec5SDimitry Andric /// pass begin/end explicitly. 17000b57cec5SDimitry Andric template <typename R, typename OutputIt, typename UnaryPredicate> 17010b57cec5SDimitry Andric OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) { 17020b57cec5SDimitry Andric return std::copy_if(adl_begin(Range), adl_end(Range), Out, P); 17030b57cec5SDimitry Andric } 17040b57cec5SDimitry Andric 17050b57cec5SDimitry Andric template <typename R, typename OutputIt> 17060b57cec5SDimitry Andric OutputIt copy(R &&Range, OutputIt Out) { 17070b57cec5SDimitry Andric return std::copy(adl_begin(Range), adl_end(Range), Out); 17080b57cec5SDimitry Andric } 17090b57cec5SDimitry Andric 1710e8d8bef9SDimitry Andric /// Provide wrappers to std::move which take ranges instead of having to 1711e8d8bef9SDimitry Andric /// pass begin/end explicitly. 1712e8d8bef9SDimitry Andric template <typename R, typename OutputIt> 1713e8d8bef9SDimitry Andric OutputIt move(R &&Range, OutputIt Out) { 1714e8d8bef9SDimitry Andric return std::move(adl_begin(Range), adl_end(Range), Out); 1715e8d8bef9SDimitry Andric } 1716e8d8bef9SDimitry Andric 17170b57cec5SDimitry Andric /// Wrapper function around std::find to detect if an element exists 17180b57cec5SDimitry Andric /// in a container. 17190b57cec5SDimitry Andric template <typename R, typename E> 17200b57cec5SDimitry Andric bool is_contained(R &&Range, const E &Element) { 17210b57cec5SDimitry Andric return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range); 17220b57cec5SDimitry Andric } 17230b57cec5SDimitry Andric 17245ffd83dbSDimitry Andric /// Wrapper function around std::is_sorted to check if elements in a range \p R 17255ffd83dbSDimitry Andric /// are sorted with respect to a comparator \p C. 17265ffd83dbSDimitry Andric template <typename R, typename Compare> bool is_sorted(R &&Range, Compare C) { 17275ffd83dbSDimitry Andric return std::is_sorted(adl_begin(Range), adl_end(Range), C); 17285ffd83dbSDimitry Andric } 17295ffd83dbSDimitry Andric 17305ffd83dbSDimitry Andric /// Wrapper function around std::is_sorted to check if elements in a range \p R 17315ffd83dbSDimitry Andric /// are sorted in non-descending order. 17325ffd83dbSDimitry Andric template <typename R> bool is_sorted(R &&Range) { 17335ffd83dbSDimitry Andric return std::is_sorted(adl_begin(Range), adl_end(Range)); 17345ffd83dbSDimitry Andric } 17355ffd83dbSDimitry Andric 17360b57cec5SDimitry Andric /// Wrapper function around std::count to count the number of times an element 17370b57cec5SDimitry Andric /// \p Element occurs in the given range \p Range. 17385ffd83dbSDimitry Andric template <typename R, typename E> auto count(R &&Range, const E &Element) { 17390b57cec5SDimitry Andric return std::count(adl_begin(Range), adl_end(Range), Element); 17400b57cec5SDimitry Andric } 17410b57cec5SDimitry Andric 17420b57cec5SDimitry Andric /// Wrapper function around std::count_if to count the number of times an 17430b57cec5SDimitry Andric /// element satisfying a given predicate occurs in a range. 17440b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 17455ffd83dbSDimitry Andric auto count_if(R &&Range, UnaryPredicate P) { 17460b57cec5SDimitry Andric return std::count_if(adl_begin(Range), adl_end(Range), P); 17470b57cec5SDimitry Andric } 17480b57cec5SDimitry Andric 17490b57cec5SDimitry Andric /// Wrapper function around std::transform to apply a function to a range and 17500b57cec5SDimitry Andric /// store the result elsewhere. 1751e8d8bef9SDimitry Andric template <typename R, typename OutputIt, typename UnaryFunction> 1752e8d8bef9SDimitry Andric OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F) { 1753e8d8bef9SDimitry Andric return std::transform(adl_begin(Range), adl_end(Range), d_first, F); 17540b57cec5SDimitry Andric } 17550b57cec5SDimitry Andric 17560b57cec5SDimitry Andric /// Provide wrappers to std::partition which take ranges instead of having to 17570b57cec5SDimitry Andric /// pass begin/end explicitly. 17580b57cec5SDimitry Andric template <typename R, typename UnaryPredicate> 17595ffd83dbSDimitry Andric auto partition(R &&Range, UnaryPredicate P) { 17600b57cec5SDimitry Andric return std::partition(adl_begin(Range), adl_end(Range), P); 17610b57cec5SDimitry Andric } 17620b57cec5SDimitry Andric 17630b57cec5SDimitry Andric /// Provide wrappers to std::lower_bound which take ranges instead of having to 17640b57cec5SDimitry Andric /// pass begin/end explicitly. 17655ffd83dbSDimitry Andric template <typename R, typename T> auto lower_bound(R &&Range, T &&Value) { 17660b57cec5SDimitry Andric return std::lower_bound(adl_begin(Range), adl_end(Range), 17670b57cec5SDimitry Andric std::forward<T>(Value)); 17680b57cec5SDimitry Andric } 17690b57cec5SDimitry Andric 17700b57cec5SDimitry Andric template <typename R, typename T, typename Compare> 17715ffd83dbSDimitry Andric auto lower_bound(R &&Range, T &&Value, Compare C) { 17720b57cec5SDimitry Andric return std::lower_bound(adl_begin(Range), adl_end(Range), 17730b57cec5SDimitry Andric std::forward<T>(Value), C); 17740b57cec5SDimitry Andric } 17750b57cec5SDimitry Andric 17760b57cec5SDimitry Andric /// Provide wrappers to std::upper_bound which take ranges instead of having to 17770b57cec5SDimitry Andric /// pass begin/end explicitly. 17785ffd83dbSDimitry Andric template <typename R, typename T> auto upper_bound(R &&Range, T &&Value) { 17790b57cec5SDimitry Andric return std::upper_bound(adl_begin(Range), adl_end(Range), 17800b57cec5SDimitry Andric std::forward<T>(Value)); 17810b57cec5SDimitry Andric } 17820b57cec5SDimitry Andric 17830b57cec5SDimitry Andric template <typename R, typename T, typename Compare> 17845ffd83dbSDimitry Andric auto upper_bound(R &&Range, T &&Value, Compare C) { 17850b57cec5SDimitry Andric return std::upper_bound(adl_begin(Range), adl_end(Range), 17860b57cec5SDimitry Andric std::forward<T>(Value), C); 17870b57cec5SDimitry Andric } 17880b57cec5SDimitry Andric 17890b57cec5SDimitry Andric template <typename R> 17900b57cec5SDimitry Andric void stable_sort(R &&Range) { 17910b57cec5SDimitry Andric std::stable_sort(adl_begin(Range), adl_end(Range)); 17920b57cec5SDimitry Andric } 17930b57cec5SDimitry Andric 17940b57cec5SDimitry Andric template <typename R, typename Compare> 17950b57cec5SDimitry Andric void stable_sort(R &&Range, Compare C) { 17960b57cec5SDimitry Andric std::stable_sort(adl_begin(Range), adl_end(Range), C); 17970b57cec5SDimitry Andric } 17980b57cec5SDimitry Andric 17990b57cec5SDimitry Andric /// Binary search for the first iterator in a range where a predicate is false. 18000b57cec5SDimitry Andric /// Requires that C is always true below some limit, and always false above it. 18010b57cec5SDimitry Andric template <typename R, typename Predicate, 18020b57cec5SDimitry Andric typename Val = decltype(*adl_begin(std::declval<R>()))> 18035ffd83dbSDimitry Andric auto partition_point(R &&Range, Predicate P) { 18040b57cec5SDimitry Andric return std::partition_point(adl_begin(Range), adl_end(Range), P); 18050b57cec5SDimitry Andric } 18060b57cec5SDimitry Andric 1807fe6060f1SDimitry Andric template<typename Range, typename Predicate> 1808fe6060f1SDimitry Andric auto unique(Range &&R, Predicate P) { 1809fe6060f1SDimitry Andric return std::unique(adl_begin(R), adl_end(R), P); 1810fe6060f1SDimitry Andric } 1811fe6060f1SDimitry Andric 1812fe6060f1SDimitry Andric /// Wrapper function around std::equal to detect if pair-wise elements between 1813fe6060f1SDimitry Andric /// two ranges are the same. 1814fe6060f1SDimitry Andric template <typename L, typename R> bool equal(L &&LRange, R &&RRange) { 1815fe6060f1SDimitry Andric return std::equal(adl_begin(LRange), adl_end(LRange), adl_begin(RRange), 1816fe6060f1SDimitry Andric adl_end(RRange)); 1817fe6060f1SDimitry Andric } 1818fe6060f1SDimitry Andric 18190b57cec5SDimitry Andric /// Wrapper function around std::equal to detect if all elements 18200b57cec5SDimitry Andric /// in a container are same. 18210b57cec5SDimitry Andric template <typename R> 18220b57cec5SDimitry Andric bool is_splat(R &&Range) { 18230b57cec5SDimitry Andric size_t range_size = size(Range); 18240b57cec5SDimitry Andric return range_size != 0 && (range_size == 1 || 18250b57cec5SDimitry Andric std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range))); 18260b57cec5SDimitry Andric } 18270b57cec5SDimitry Andric 18280b57cec5SDimitry Andric /// Provide a container algorithm similar to C++ Library Fundamentals v2's 18290b57cec5SDimitry Andric /// `erase_if` which is equivalent to: 18300b57cec5SDimitry Andric /// 18310b57cec5SDimitry Andric /// C.erase(remove_if(C, pred), C.end()); 18320b57cec5SDimitry Andric /// 18330b57cec5SDimitry Andric /// This version works for any container with an erase method call accepting 18340b57cec5SDimitry Andric /// two iterators. 18350b57cec5SDimitry Andric template <typename Container, typename UnaryPredicate> 18360b57cec5SDimitry Andric void erase_if(Container &C, UnaryPredicate P) { 18370b57cec5SDimitry Andric C.erase(remove_if(C, P), C.end()); 18380b57cec5SDimitry Andric } 18390b57cec5SDimitry Andric 1840e8d8bef9SDimitry Andric /// Wrapper function to remove a value from a container: 1841e8d8bef9SDimitry Andric /// 1842e8d8bef9SDimitry Andric /// C.erase(remove(C.begin(), C.end(), V), C.end()); 1843e8d8bef9SDimitry Andric template <typename Container, typename ValueType> 1844e8d8bef9SDimitry Andric void erase_value(Container &C, ValueType V) { 1845e8d8bef9SDimitry Andric C.erase(std::remove(C.begin(), C.end(), V), C.end()); 1846e8d8bef9SDimitry Andric } 1847e8d8bef9SDimitry Andric 1848e8d8bef9SDimitry Andric /// Wrapper function to append a range to a container. 1849e8d8bef9SDimitry Andric /// 1850e8d8bef9SDimitry Andric /// C.insert(C.end(), R.begin(), R.end()); 1851e8d8bef9SDimitry Andric template <typename Container, typename Range> 1852e8d8bef9SDimitry Andric inline void append_range(Container &C, Range &&R) { 1853e8d8bef9SDimitry Andric C.insert(C.end(), R.begin(), R.end()); 1854e8d8bef9SDimitry Andric } 1855e8d8bef9SDimitry Andric 18560b57cec5SDimitry Andric /// Given a sequence container Cont, replace the range [ContIt, ContEnd) with 18570b57cec5SDimitry Andric /// the range [ValIt, ValEnd) (which is not from the same container). 18580b57cec5SDimitry Andric template<typename Container, typename RandomAccessIterator> 18590b57cec5SDimitry Andric void replace(Container &Cont, typename Container::iterator ContIt, 18600b57cec5SDimitry Andric typename Container::iterator ContEnd, RandomAccessIterator ValIt, 18610b57cec5SDimitry Andric RandomAccessIterator ValEnd) { 18620b57cec5SDimitry Andric while (true) { 18630b57cec5SDimitry Andric if (ValIt == ValEnd) { 18640b57cec5SDimitry Andric Cont.erase(ContIt, ContEnd); 18650b57cec5SDimitry Andric return; 18660b57cec5SDimitry Andric } else if (ContIt == ContEnd) { 18670b57cec5SDimitry Andric Cont.insert(ContIt, ValIt, ValEnd); 18680b57cec5SDimitry Andric return; 18690b57cec5SDimitry Andric } 18700b57cec5SDimitry Andric *ContIt++ = *ValIt++; 18710b57cec5SDimitry Andric } 18720b57cec5SDimitry Andric } 18730b57cec5SDimitry Andric 18740b57cec5SDimitry Andric /// Given a sequence container Cont, replace the range [ContIt, ContEnd) with 18750b57cec5SDimitry Andric /// the range R. 18760b57cec5SDimitry Andric template<typename Container, typename Range = std::initializer_list< 18770b57cec5SDimitry Andric typename Container::value_type>> 18780b57cec5SDimitry Andric void replace(Container &Cont, typename Container::iterator ContIt, 18790b57cec5SDimitry Andric typename Container::iterator ContEnd, Range R) { 18800b57cec5SDimitry Andric replace(Cont, ContIt, ContEnd, R.begin(), R.end()); 18810b57cec5SDimitry Andric } 18820b57cec5SDimitry Andric 18835ffd83dbSDimitry Andric /// An STL-style algorithm similar to std::for_each that applies a second 18845ffd83dbSDimitry Andric /// functor between every pair of elements. 18855ffd83dbSDimitry Andric /// 18865ffd83dbSDimitry Andric /// This provides the control flow logic to, for example, print a 18875ffd83dbSDimitry Andric /// comma-separated list: 18885ffd83dbSDimitry Andric /// \code 18895ffd83dbSDimitry Andric /// interleave(names.begin(), names.end(), 18905ffd83dbSDimitry Andric /// [&](StringRef name) { os << name; }, 18915ffd83dbSDimitry Andric /// [&] { os << ", "; }); 18925ffd83dbSDimitry Andric /// \endcode 18935ffd83dbSDimitry Andric template <typename ForwardIterator, typename UnaryFunctor, 18945ffd83dbSDimitry Andric typename NullaryFunctor, 18955ffd83dbSDimitry Andric typename = typename std::enable_if< 18965ffd83dbSDimitry Andric !std::is_constructible<StringRef, UnaryFunctor>::value && 18975ffd83dbSDimitry Andric !std::is_constructible<StringRef, NullaryFunctor>::value>::type> 18985ffd83dbSDimitry Andric inline void interleave(ForwardIterator begin, ForwardIterator end, 18995ffd83dbSDimitry Andric UnaryFunctor each_fn, NullaryFunctor between_fn) { 19005ffd83dbSDimitry Andric if (begin == end) 19015ffd83dbSDimitry Andric return; 19025ffd83dbSDimitry Andric each_fn(*begin); 19035ffd83dbSDimitry Andric ++begin; 19045ffd83dbSDimitry Andric for (; begin != end; ++begin) { 19055ffd83dbSDimitry Andric between_fn(); 19065ffd83dbSDimitry Andric each_fn(*begin); 19075ffd83dbSDimitry Andric } 19085ffd83dbSDimitry Andric } 19095ffd83dbSDimitry Andric 19105ffd83dbSDimitry Andric template <typename Container, typename UnaryFunctor, typename NullaryFunctor, 19115ffd83dbSDimitry Andric typename = typename std::enable_if< 19125ffd83dbSDimitry Andric !std::is_constructible<StringRef, UnaryFunctor>::value && 19135ffd83dbSDimitry Andric !std::is_constructible<StringRef, NullaryFunctor>::value>::type> 19145ffd83dbSDimitry Andric inline void interleave(const Container &c, UnaryFunctor each_fn, 19155ffd83dbSDimitry Andric NullaryFunctor between_fn) { 19165ffd83dbSDimitry Andric interleave(c.begin(), c.end(), each_fn, between_fn); 19175ffd83dbSDimitry Andric } 19185ffd83dbSDimitry Andric 19195ffd83dbSDimitry Andric /// Overload of interleave for the common case of string separator. 19205ffd83dbSDimitry Andric template <typename Container, typename UnaryFunctor, typename StreamT, 19215ffd83dbSDimitry Andric typename T = detail::ValueOfRange<Container>> 19225ffd83dbSDimitry Andric inline void interleave(const Container &c, StreamT &os, UnaryFunctor each_fn, 19235ffd83dbSDimitry Andric const StringRef &separator) { 19245ffd83dbSDimitry Andric interleave(c.begin(), c.end(), each_fn, [&] { os << separator; }); 19255ffd83dbSDimitry Andric } 19265ffd83dbSDimitry Andric template <typename Container, typename StreamT, 19275ffd83dbSDimitry Andric typename T = detail::ValueOfRange<Container>> 19285ffd83dbSDimitry Andric inline void interleave(const Container &c, StreamT &os, 19295ffd83dbSDimitry Andric const StringRef &separator) { 19305ffd83dbSDimitry Andric interleave( 19315ffd83dbSDimitry Andric c, os, [&](const T &a) { os << a; }, separator); 19325ffd83dbSDimitry Andric } 19335ffd83dbSDimitry Andric 19345ffd83dbSDimitry Andric template <typename Container, typename UnaryFunctor, typename StreamT, 19355ffd83dbSDimitry Andric typename T = detail::ValueOfRange<Container>> 19365ffd83dbSDimitry Andric inline void interleaveComma(const Container &c, StreamT &os, 19375ffd83dbSDimitry Andric UnaryFunctor each_fn) { 19385ffd83dbSDimitry Andric interleave(c, os, each_fn, ", "); 19395ffd83dbSDimitry Andric } 19405ffd83dbSDimitry Andric template <typename Container, typename StreamT, 19415ffd83dbSDimitry Andric typename T = detail::ValueOfRange<Container>> 19425ffd83dbSDimitry Andric inline void interleaveComma(const Container &c, StreamT &os) { 19435ffd83dbSDimitry Andric interleaveComma(c, os, [&](const T &a) { os << a; }); 19445ffd83dbSDimitry Andric } 19455ffd83dbSDimitry Andric 19460b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 19470b57cec5SDimitry Andric // Extra additions to <memory> 19480b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 19490b57cec5SDimitry Andric 19500b57cec5SDimitry Andric struct FreeDeleter { 19510b57cec5SDimitry Andric void operator()(void* v) { 19520b57cec5SDimitry Andric ::free(v); 19530b57cec5SDimitry Andric } 19540b57cec5SDimitry Andric }; 19550b57cec5SDimitry Andric 19560b57cec5SDimitry Andric template<typename First, typename Second> 19570b57cec5SDimitry Andric struct pair_hash { 19580b57cec5SDimitry Andric size_t operator()(const std::pair<First, Second> &P) const { 19590b57cec5SDimitry Andric return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second); 19600b57cec5SDimitry Andric } 19610b57cec5SDimitry Andric }; 19620b57cec5SDimitry Andric 19630b57cec5SDimitry Andric /// Binary functor that adapts to any other binary functor after dereferencing 19640b57cec5SDimitry Andric /// operands. 19650b57cec5SDimitry Andric template <typename T> struct deref { 19660b57cec5SDimitry Andric T func; 19670b57cec5SDimitry Andric 19680b57cec5SDimitry Andric // Could be further improved to cope with non-derivable functors and 19690b57cec5SDimitry Andric // non-binary functors (should be a variadic template member function 19700b57cec5SDimitry Andric // operator()). 19715ffd83dbSDimitry Andric template <typename A, typename B> auto operator()(A &lhs, B &rhs) const { 19720b57cec5SDimitry Andric assert(lhs); 19730b57cec5SDimitry Andric assert(rhs); 19740b57cec5SDimitry Andric return func(*lhs, *rhs); 19750b57cec5SDimitry Andric } 19760b57cec5SDimitry Andric }; 19770b57cec5SDimitry Andric 19780b57cec5SDimitry Andric namespace detail { 19790b57cec5SDimitry Andric 19800b57cec5SDimitry Andric template <typename R> class enumerator_iter; 19810b57cec5SDimitry Andric 19820b57cec5SDimitry Andric template <typename R> struct result_pair { 19830b57cec5SDimitry Andric using value_reference = 19840b57cec5SDimitry Andric typename std::iterator_traits<IterOfRange<R>>::reference; 19850b57cec5SDimitry Andric 19860b57cec5SDimitry Andric friend class enumerator_iter<R>; 19870b57cec5SDimitry Andric 19880b57cec5SDimitry Andric result_pair() = default; 19890b57cec5SDimitry Andric result_pair(std::size_t Index, IterOfRange<R> Iter) 19900b57cec5SDimitry Andric : Index(Index), Iter(Iter) {} 19910b57cec5SDimitry Andric 1992fe6060f1SDimitry Andric result_pair(const result_pair<R> &Other) 1993480093f4SDimitry Andric : Index(Other.Index), Iter(Other.Iter) {} 1994fe6060f1SDimitry Andric result_pair &operator=(const result_pair &Other) { 19950b57cec5SDimitry Andric Index = Other.Index; 19960b57cec5SDimitry Andric Iter = Other.Iter; 19970b57cec5SDimitry Andric return *this; 19980b57cec5SDimitry Andric } 19990b57cec5SDimitry Andric 20000b57cec5SDimitry Andric std::size_t index() const { return Index; } 2001349cc55cSDimitry Andric value_reference value() const { return *Iter; } 20020b57cec5SDimitry Andric 20030b57cec5SDimitry Andric private: 20040b57cec5SDimitry Andric std::size_t Index = std::numeric_limits<std::size_t>::max(); 20050b57cec5SDimitry Andric IterOfRange<R> Iter; 20060b57cec5SDimitry Andric }; 20070b57cec5SDimitry Andric 20080b57cec5SDimitry Andric template <typename R> 20090b57cec5SDimitry Andric class enumerator_iter 2010349cc55cSDimitry Andric : public iterator_facade_base<enumerator_iter<R>, std::forward_iterator_tag, 2011349cc55cSDimitry Andric const result_pair<R>> { 20120b57cec5SDimitry Andric using result_type = result_pair<R>; 20130b57cec5SDimitry Andric 20140b57cec5SDimitry Andric public: 20150b57cec5SDimitry Andric explicit enumerator_iter(IterOfRange<R> EndIter) 20160b57cec5SDimitry Andric : Result(std::numeric_limits<size_t>::max(), EndIter) {} 20170b57cec5SDimitry Andric 20180b57cec5SDimitry Andric enumerator_iter(std::size_t Index, IterOfRange<R> Iter) 20190b57cec5SDimitry Andric : Result(Index, Iter) {} 20200b57cec5SDimitry Andric 20210b57cec5SDimitry Andric const result_type &operator*() const { return Result; } 20220b57cec5SDimitry Andric 2023fe6060f1SDimitry Andric enumerator_iter &operator++() { 20240b57cec5SDimitry Andric assert(Result.Index != std::numeric_limits<size_t>::max()); 20250b57cec5SDimitry Andric ++Result.Iter; 20260b57cec5SDimitry Andric ++Result.Index; 20270b57cec5SDimitry Andric return *this; 20280b57cec5SDimitry Andric } 20290b57cec5SDimitry Andric 2030fe6060f1SDimitry Andric bool operator==(const enumerator_iter &RHS) const { 20310b57cec5SDimitry Andric // Don't compare indices here, only iterators. It's possible for an end 20320b57cec5SDimitry Andric // iterator to have different indices depending on whether it was created 20330b57cec5SDimitry Andric // by calling std::end() versus incrementing a valid iterator. 20340b57cec5SDimitry Andric return Result.Iter == RHS.Result.Iter; 20350b57cec5SDimitry Andric } 20360b57cec5SDimitry Andric 2037fe6060f1SDimitry Andric enumerator_iter(const enumerator_iter &Other) : Result(Other.Result) {} 2038fe6060f1SDimitry Andric enumerator_iter &operator=(const enumerator_iter &Other) { 20390b57cec5SDimitry Andric Result = Other.Result; 20400b57cec5SDimitry Andric return *this; 20410b57cec5SDimitry Andric } 20420b57cec5SDimitry Andric 20430b57cec5SDimitry Andric private: 20440b57cec5SDimitry Andric result_type Result; 20450b57cec5SDimitry Andric }; 20460b57cec5SDimitry Andric 20470b57cec5SDimitry Andric template <typename R> class enumerator { 20480b57cec5SDimitry Andric public: 20490b57cec5SDimitry Andric explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {} 20500b57cec5SDimitry Andric 20510b57cec5SDimitry Andric enumerator_iter<R> begin() { 20520b57cec5SDimitry Andric return enumerator_iter<R>(0, std::begin(TheRange)); 20530b57cec5SDimitry Andric } 20544824e7fdSDimitry Andric enumerator_iter<R> begin() const { 20554824e7fdSDimitry Andric return enumerator_iter<R>(0, std::begin(TheRange)); 20564824e7fdSDimitry Andric } 20570b57cec5SDimitry Andric 20580b57cec5SDimitry Andric enumerator_iter<R> end() { 20590b57cec5SDimitry Andric return enumerator_iter<R>(std::end(TheRange)); 20600b57cec5SDimitry Andric } 20614824e7fdSDimitry Andric enumerator_iter<R> end() const { 20624824e7fdSDimitry Andric return enumerator_iter<R>(std::end(TheRange)); 20634824e7fdSDimitry Andric } 20640b57cec5SDimitry Andric 20650b57cec5SDimitry Andric private: 20660b57cec5SDimitry Andric R TheRange; 20670b57cec5SDimitry Andric }; 20680b57cec5SDimitry Andric 20690b57cec5SDimitry Andric } // end namespace detail 20700b57cec5SDimitry Andric 20710b57cec5SDimitry Andric /// Given an input range, returns a new range whose values are are pair (A,B) 20720b57cec5SDimitry Andric /// such that A is the 0-based index of the item in the sequence, and B is 20730b57cec5SDimitry Andric /// the value from the original sequence. Example: 20740b57cec5SDimitry Andric /// 20750b57cec5SDimitry Andric /// std::vector<char> Items = {'A', 'B', 'C', 'D'}; 20760b57cec5SDimitry Andric /// for (auto X : enumerate(Items)) { 20770b57cec5SDimitry Andric /// printf("Item %d - %c\n", X.index(), X.value()); 20780b57cec5SDimitry Andric /// } 20790b57cec5SDimitry Andric /// 20800b57cec5SDimitry Andric /// Output: 20810b57cec5SDimitry Andric /// Item 0 - A 20820b57cec5SDimitry Andric /// Item 1 - B 20830b57cec5SDimitry Andric /// Item 2 - C 20840b57cec5SDimitry Andric /// Item 3 - D 20850b57cec5SDimitry Andric /// 20860b57cec5SDimitry Andric template <typename R> detail::enumerator<R> enumerate(R &&TheRange) { 20870b57cec5SDimitry Andric return detail::enumerator<R>(std::forward<R>(TheRange)); 20880b57cec5SDimitry Andric } 20890b57cec5SDimitry Andric 20900b57cec5SDimitry Andric namespace detail { 20910b57cec5SDimitry Andric 20920b57cec5SDimitry Andric template <typename F, typename Tuple, std::size_t... I> 20935ffd83dbSDimitry Andric decltype(auto) apply_tuple_impl(F &&f, Tuple &&t, std::index_sequence<I...>) { 20940b57cec5SDimitry Andric return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...); 20950b57cec5SDimitry Andric } 20960b57cec5SDimitry Andric 20970b57cec5SDimitry Andric } // end namespace detail 20980b57cec5SDimitry Andric 20990b57cec5SDimitry Andric /// Given an input tuple (a1, a2, ..., an), pass the arguments of the 21000b57cec5SDimitry Andric /// tuple variadically to f as if by calling f(a1, a2, ..., an) and 21010b57cec5SDimitry Andric /// return the result. 21020b57cec5SDimitry Andric template <typename F, typename Tuple> 21035ffd83dbSDimitry Andric decltype(auto) apply_tuple(F &&f, Tuple &&t) { 21048bcb0991SDimitry Andric using Indices = std::make_index_sequence< 21050b57cec5SDimitry Andric std::tuple_size<typename std::decay<Tuple>::type>::value>; 21060b57cec5SDimitry Andric 21070b57cec5SDimitry Andric return detail::apply_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t), 21080b57cec5SDimitry Andric Indices{}); 21090b57cec5SDimitry Andric } 21100b57cec5SDimitry Andric 2111349cc55cSDimitry Andric namespace detail { 2112349cc55cSDimitry Andric 2113349cc55cSDimitry Andric template <typename Predicate, typename... Args> 2114349cc55cSDimitry Andric bool all_of_zip_predicate_first(Predicate &&P, Args &&...args) { 2115349cc55cSDimitry Andric auto z = zip(args...); 2116349cc55cSDimitry Andric auto it = z.begin(); 2117349cc55cSDimitry Andric auto end = z.end(); 2118349cc55cSDimitry Andric while (it != end) { 2119349cc55cSDimitry Andric if (!apply_tuple([&](auto &&...args) { return P(args...); }, *it)) 2120349cc55cSDimitry Andric return false; 2121349cc55cSDimitry Andric ++it; 2122349cc55cSDimitry Andric } 2123349cc55cSDimitry Andric return it.all_equals(end); 2124349cc55cSDimitry Andric } 2125349cc55cSDimitry Andric 2126349cc55cSDimitry Andric // Just an adaptor to switch the order of argument and have the predicate before 2127349cc55cSDimitry Andric // the zipped inputs. 2128349cc55cSDimitry Andric template <typename... ArgsThenPredicate, size_t... InputIndexes> 2129349cc55cSDimitry Andric bool all_of_zip_predicate_last( 2130349cc55cSDimitry Andric std::tuple<ArgsThenPredicate...> argsThenPredicate, 2131349cc55cSDimitry Andric std::index_sequence<InputIndexes...>) { 2132349cc55cSDimitry Andric auto constexpr OutputIndex = 2133349cc55cSDimitry Andric std::tuple_size<decltype(argsThenPredicate)>::value - 1; 2134349cc55cSDimitry Andric return all_of_zip_predicate_first(std::get<OutputIndex>(argsThenPredicate), 2135349cc55cSDimitry Andric std::get<InputIndexes>(argsThenPredicate)...); 2136349cc55cSDimitry Andric } 2137349cc55cSDimitry Andric 2138349cc55cSDimitry Andric } // end namespace detail 2139349cc55cSDimitry Andric 2140349cc55cSDimitry Andric /// Compare two zipped ranges using the provided predicate (as last argument). 2141349cc55cSDimitry Andric /// Return true if all elements satisfy the predicate and false otherwise. 2142349cc55cSDimitry Andric // Return false if the zipped iterator aren't all at end (size mismatch). 2143349cc55cSDimitry Andric template <typename... ArgsAndPredicate> 2144349cc55cSDimitry Andric bool all_of_zip(ArgsAndPredicate &&...argsAndPredicate) { 2145349cc55cSDimitry Andric return detail::all_of_zip_predicate_last( 2146349cc55cSDimitry Andric std::forward_as_tuple(argsAndPredicate...), 2147349cc55cSDimitry Andric std::make_index_sequence<sizeof...(argsAndPredicate) - 1>{}); 2148349cc55cSDimitry Andric } 2149349cc55cSDimitry Andric 21500b57cec5SDimitry Andric /// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N) 21510b57cec5SDimitry Andric /// time. Not meant for use with random-access iterators. 21525ffd83dbSDimitry Andric /// Can optionally take a predicate to filter lazily some items. 21535ffd83dbSDimitry Andric template <typename IterTy, 21545ffd83dbSDimitry Andric typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)> 21550b57cec5SDimitry Andric bool hasNItems( 21560b57cec5SDimitry Andric IterTy &&Begin, IterTy &&End, unsigned N, 21575ffd83dbSDimitry Andric Pred &&ShouldBeCounted = 21585ffd83dbSDimitry Andric [](const decltype(*std::declval<IterTy>()) &) { return true; }, 21595ffd83dbSDimitry Andric std::enable_if_t< 2160e8d8bef9SDimitry Andric !std::is_base_of<std::random_access_iterator_tag, 2161e8d8bef9SDimitry Andric typename std::iterator_traits<std::remove_reference_t< 2162e8d8bef9SDimitry Andric decltype(Begin)>>::iterator_category>::value, 21635ffd83dbSDimitry Andric void> * = nullptr) { 21645ffd83dbSDimitry Andric for (; N; ++Begin) { 21650b57cec5SDimitry Andric if (Begin == End) 21660b57cec5SDimitry Andric return false; // Too few. 21675ffd83dbSDimitry Andric N -= ShouldBeCounted(*Begin); 21685ffd83dbSDimitry Andric } 21695ffd83dbSDimitry Andric for (; Begin != End; ++Begin) 21705ffd83dbSDimitry Andric if (ShouldBeCounted(*Begin)) 21715ffd83dbSDimitry Andric return false; // Too many. 21725ffd83dbSDimitry Andric return true; 21730b57cec5SDimitry Andric } 21740b57cec5SDimitry Andric 21750b57cec5SDimitry Andric /// Return true if the sequence [Begin, End) has N or more items. Runs in O(N) 21760b57cec5SDimitry Andric /// time. Not meant for use with random-access iterators. 21775ffd83dbSDimitry Andric /// Can optionally take a predicate to lazily filter some items. 21785ffd83dbSDimitry Andric template <typename IterTy, 21795ffd83dbSDimitry Andric typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)> 21800b57cec5SDimitry Andric bool hasNItemsOrMore( 21810b57cec5SDimitry Andric IterTy &&Begin, IterTy &&End, unsigned N, 21825ffd83dbSDimitry Andric Pred &&ShouldBeCounted = 21835ffd83dbSDimitry Andric [](const decltype(*std::declval<IterTy>()) &) { return true; }, 21845ffd83dbSDimitry Andric std::enable_if_t< 2185e8d8bef9SDimitry Andric !std::is_base_of<std::random_access_iterator_tag, 2186e8d8bef9SDimitry Andric typename std::iterator_traits<std::remove_reference_t< 2187e8d8bef9SDimitry Andric decltype(Begin)>>::iterator_category>::value, 21885ffd83dbSDimitry Andric void> * = nullptr) { 21895ffd83dbSDimitry Andric for (; N; ++Begin) { 21900b57cec5SDimitry Andric if (Begin == End) 21910b57cec5SDimitry Andric return false; // Too few. 21925ffd83dbSDimitry Andric N -= ShouldBeCounted(*Begin); 21935ffd83dbSDimitry Andric } 21940b57cec5SDimitry Andric return true; 21950b57cec5SDimitry Andric } 21960b57cec5SDimitry Andric 21975ffd83dbSDimitry Andric /// Returns true if the sequence [Begin, End) has N or less items. Can 21985ffd83dbSDimitry Andric /// optionally take a predicate to lazily filter some items. 21995ffd83dbSDimitry Andric template <typename IterTy, 22005ffd83dbSDimitry Andric typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)> 22015ffd83dbSDimitry Andric bool hasNItemsOrLess( 22025ffd83dbSDimitry Andric IterTy &&Begin, IterTy &&End, unsigned N, 22035ffd83dbSDimitry Andric Pred &&ShouldBeCounted = [](const decltype(*std::declval<IterTy>()) &) { 22045ffd83dbSDimitry Andric return true; 22055ffd83dbSDimitry Andric }) { 22065ffd83dbSDimitry Andric assert(N != std::numeric_limits<unsigned>::max()); 22075ffd83dbSDimitry Andric return !hasNItemsOrMore(Begin, End, N + 1, ShouldBeCounted); 22085ffd83dbSDimitry Andric } 22095ffd83dbSDimitry Andric 22105ffd83dbSDimitry Andric /// Returns true if the given container has exactly N items 22115ffd83dbSDimitry Andric template <typename ContainerTy> bool hasNItems(ContainerTy &&C, unsigned N) { 22125ffd83dbSDimitry Andric return hasNItems(std::begin(C), std::end(C), N); 22135ffd83dbSDimitry Andric } 22145ffd83dbSDimitry Andric 22155ffd83dbSDimitry Andric /// Returns true if the given container has N or more items 22165ffd83dbSDimitry Andric template <typename ContainerTy> 22175ffd83dbSDimitry Andric bool hasNItemsOrMore(ContainerTy &&C, unsigned N) { 22185ffd83dbSDimitry Andric return hasNItemsOrMore(std::begin(C), std::end(C), N); 22195ffd83dbSDimitry Andric } 22205ffd83dbSDimitry Andric 22215ffd83dbSDimitry Andric /// Returns true if the given container has N or less items 22225ffd83dbSDimitry Andric template <typename ContainerTy> 22235ffd83dbSDimitry Andric bool hasNItemsOrLess(ContainerTy &&C, unsigned N) { 22245ffd83dbSDimitry Andric return hasNItemsOrLess(std::begin(C), std::end(C), N); 22255ffd83dbSDimitry Andric } 22265ffd83dbSDimitry Andric 22270b57cec5SDimitry Andric /// Returns a raw pointer that represents the same address as the argument. 22280b57cec5SDimitry Andric /// 22295ffd83dbSDimitry Andric /// This implementation can be removed once we move to C++20 where it's defined 22305ffd83dbSDimitry Andric /// as std::to_address(). 22310b57cec5SDimitry Andric /// 22320b57cec5SDimitry Andric /// The std::pointer_traits<>::to_address(p) variations of these overloads has 22330b57cec5SDimitry Andric /// not been implemented. 22345ffd83dbSDimitry Andric template <class Ptr> auto to_address(const Ptr &P) { return P.operator->(); } 22350b57cec5SDimitry Andric template <class T> constexpr T *to_address(T *P) { return P; } 22360b57cec5SDimitry Andric 22370b57cec5SDimitry Andric } // end namespace llvm 22380b57cec5SDimitry Andric 22390b57cec5SDimitry Andric #endif // LLVM_ADT_STLEXTRAS_H 2240