xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ADT/STLExtras.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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 //===----------------------------------------------------------------------===//
81fd87a68SDimitry Andric ///
91fd87a68SDimitry Andric /// \file
101fd87a68SDimitry Andric /// This file contains some templates that are useful if you are working with
111fd87a68SDimitry Andric /// the STL at all.
121fd87a68SDimitry Andric ///
131fd87a68SDimitry Andric /// No library is required when using these functions.
141fd87a68SDimitry Andric ///
150b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
160b57cec5SDimitry Andric 
170b57cec5SDimitry Andric #ifndef LLVM_ADT_STLEXTRAS_H
180b57cec5SDimitry Andric #define LLVM_ADT_STLEXTRAS_H
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric #include "llvm/ADT/Optional.h"
211fd87a68SDimitry Andric #include "llvm/ADT/STLArrayExtras.h"
22fe6060f1SDimitry Andric #include "llvm/ADT/STLForwardCompat.h"
2304eeddc0SDimitry Andric #include "llvm/ADT/STLFunctionalExtras.h"
241fd87a68SDimitry Andric #include "llvm/ADT/identity.h"
250b57cec5SDimitry Andric #include "llvm/ADT/iterator.h"
260b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
270b57cec5SDimitry Andric #include "llvm/Config/abi-breaking.h"
280b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
290b57cec5SDimitry Andric #include <algorithm>
300b57cec5SDimitry Andric #include <cassert>
310b57cec5SDimitry Andric #include <cstddef>
320b57cec5SDimitry Andric #include <cstdint>
330b57cec5SDimitry Andric #include <cstdlib>
340b57cec5SDimitry Andric #include <functional>
350b57cec5SDimitry Andric #include <initializer_list>
360b57cec5SDimitry Andric #include <iterator>
370b57cec5SDimitry Andric #include <limits>
380b57cec5SDimitry Andric #include <memory>
390b57cec5SDimitry Andric #include <tuple>
400b57cec5SDimitry Andric #include <type_traits>
410b57cec5SDimitry Andric #include <utility>
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
440b57cec5SDimitry Andric #include <random> // for std::mt19937
450b57cec5SDimitry Andric #endif
460b57cec5SDimitry Andric 
470b57cec5SDimitry Andric namespace llvm {
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric // Only used by compiler if both template types are the same.  Useful when
500b57cec5SDimitry Andric // using SFINAE to test for the existence of member functions.
510b57cec5SDimitry Andric template <typename T, T> struct SameType;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric namespace detail {
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric template <typename RangeT>
560b57cec5SDimitry Andric using IterOfRange = decltype(std::begin(std::declval<RangeT &>()));
570b57cec5SDimitry Andric 
585ffd83dbSDimitry Andric template <typename RangeT>
595ffd83dbSDimitry Andric using ValueOfRange = typename std::remove_reference<decltype(
605ffd83dbSDimitry Andric     *std::begin(std::declval<RangeT &>()))>::type;
615ffd83dbSDimitry Andric 
620b57cec5SDimitry Andric } // end namespace detail
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
650b57cec5SDimitry Andric //     Extra additions to <type_traits>
660b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric template <typename T> struct make_const_ptr {
690b57cec5SDimitry Andric   using type =
700b57cec5SDimitry Andric       typename std::add_pointer<typename std::add_const<T>::type>::type;
710b57cec5SDimitry Andric };
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric template <typename T> struct make_const_ref {
740b57cec5SDimitry Andric   using type = typename std::add_lvalue_reference<
750b57cec5SDimitry Andric       typename std::add_const<T>::type>::type;
760b57cec5SDimitry Andric };
770b57cec5SDimitry Andric 
785ffd83dbSDimitry Andric namespace detail {
795ffd83dbSDimitry Andric template <typename...> using void_t = void;
805ffd83dbSDimitry Andric template <class, template <class...> class Op, class... Args> struct detector {
815ffd83dbSDimitry Andric   using value_t = std::false_type;
825ffd83dbSDimitry Andric };
835ffd83dbSDimitry Andric template <template <class...> class Op, class... Args>
845ffd83dbSDimitry Andric struct detector<void_t<Op<Args...>>, Op, Args...> {
855ffd83dbSDimitry Andric   using value_t = std::true_type;
865ffd83dbSDimitry Andric };
875ffd83dbSDimitry Andric } // end namespace detail
885ffd83dbSDimitry Andric 
89fe6060f1SDimitry Andric /// Detects if a given trait holds for some set of arguments 'Args'.
90fe6060f1SDimitry Andric /// For example, the given trait could be used to detect if a given type
91fe6060f1SDimitry Andric /// has a copy assignment operator:
92fe6060f1SDimitry Andric ///   template<class T>
93fe6060f1SDimitry Andric ///   using has_copy_assign_t = decltype(std::declval<T&>()
94fe6060f1SDimitry Andric ///                                                 = std::declval<const T&>());
95fe6060f1SDimitry Andric ///   bool fooHasCopyAssign = is_detected<has_copy_assign_t, FooClass>::value;
965ffd83dbSDimitry Andric template <template <class...> class Op, class... Args>
975ffd83dbSDimitry Andric using is_detected = typename detail::detector<void, Op, Args...>::value_t;
985ffd83dbSDimitry Andric 
995ffd83dbSDimitry Andric namespace detail {
1005ffd83dbSDimitry Andric template <typename Callable, typename... Args>
1015ffd83dbSDimitry Andric using is_invocable =
1025ffd83dbSDimitry Andric     decltype(std::declval<Callable &>()(std::declval<Args>()...));
1035ffd83dbSDimitry Andric } // namespace detail
1045ffd83dbSDimitry Andric 
105fe6060f1SDimitry Andric /// Check if a Callable type can be invoked with the given set of arg types.
1065ffd83dbSDimitry Andric template <typename Callable, typename... Args>
1075ffd83dbSDimitry Andric using is_invocable = is_detected<detail::is_invocable, Callable, Args...>;
1085ffd83dbSDimitry Andric 
1095ffd83dbSDimitry Andric /// This class provides various trait information about a callable object.
1105ffd83dbSDimitry Andric ///   * To access the number of arguments: Traits::num_args
1115ffd83dbSDimitry Andric ///   * To access the type of an argument: Traits::arg_t<Index>
1125ffd83dbSDimitry Andric ///   * To access the type of the result:  Traits::result_t
1135ffd83dbSDimitry Andric template <typename T, bool isClass = std::is_class<T>::value>
1145ffd83dbSDimitry Andric struct function_traits : public function_traits<decltype(&T::operator())> {};
1155ffd83dbSDimitry Andric 
1165ffd83dbSDimitry Andric /// Overload for class function types.
1175ffd83dbSDimitry Andric template <typename ClassType, typename ReturnType, typename... Args>
1185ffd83dbSDimitry Andric struct function_traits<ReturnType (ClassType::*)(Args...) const, false> {
1195ffd83dbSDimitry Andric   /// The number of arguments to this function.
1205ffd83dbSDimitry Andric   enum { num_args = sizeof...(Args) };
1215ffd83dbSDimitry Andric 
1225ffd83dbSDimitry Andric   /// The result type of this function.
1235ffd83dbSDimitry Andric   using result_t = ReturnType;
1245ffd83dbSDimitry Andric 
1255ffd83dbSDimitry Andric   /// The type of an argument to this function.
1265ffd83dbSDimitry Andric   template <size_t Index>
1275ffd83dbSDimitry Andric   using arg_t = typename std::tuple_element<Index, std::tuple<Args...>>::type;
1285ffd83dbSDimitry Andric };
1295ffd83dbSDimitry Andric /// Overload for class function types.
1305ffd83dbSDimitry Andric template <typename ClassType, typename ReturnType, typename... Args>
1315ffd83dbSDimitry Andric struct function_traits<ReturnType (ClassType::*)(Args...), false>
132*81ad6265SDimitry Andric     : public function_traits<ReturnType (ClassType::*)(Args...) const> {};
1335ffd83dbSDimitry Andric /// Overload for non-class function types.
1345ffd83dbSDimitry Andric template <typename ReturnType, typename... Args>
1355ffd83dbSDimitry Andric struct function_traits<ReturnType (*)(Args...), false> {
1365ffd83dbSDimitry Andric   /// The number of arguments to this function.
1375ffd83dbSDimitry Andric   enum { num_args = sizeof...(Args) };
1385ffd83dbSDimitry Andric 
1395ffd83dbSDimitry Andric   /// The result type of this function.
1405ffd83dbSDimitry Andric   using result_t = ReturnType;
1415ffd83dbSDimitry Andric 
1425ffd83dbSDimitry Andric   /// The type of an argument to this function.
1435ffd83dbSDimitry Andric   template <size_t i>
1445ffd83dbSDimitry Andric   using arg_t = typename std::tuple_element<i, std::tuple<Args...>>::type;
1455ffd83dbSDimitry Andric };
146*81ad6265SDimitry Andric template <typename ReturnType, typename... Args>
147*81ad6265SDimitry Andric struct function_traits<ReturnType (*const)(Args...), false>
148*81ad6265SDimitry Andric     : public function_traits<ReturnType (*)(Args...)> {};
1495ffd83dbSDimitry Andric /// Overload for non-class function type references.
1505ffd83dbSDimitry Andric template <typename ReturnType, typename... Args>
1515ffd83dbSDimitry Andric struct function_traits<ReturnType (&)(Args...), false>
1525ffd83dbSDimitry Andric     : public function_traits<ReturnType (*)(Args...)> {};
1535ffd83dbSDimitry Andric 
1540eae32dcSDimitry Andric /// traits class for checking whether type T is one of any of the given
1550eae32dcSDimitry Andric /// types in the variadic list.
1560eae32dcSDimitry Andric template <typename T, typename... Ts>
1570eae32dcSDimitry Andric using is_one_of = disjunction<std::is_same<T, Ts>...>;
1580eae32dcSDimitry Andric 
1590eae32dcSDimitry Andric /// traits class for checking whether type T is a base class for all
1600eae32dcSDimitry Andric ///  the given types in the variadic list.
1610eae32dcSDimitry Andric template <typename T, typename... Ts>
1620eae32dcSDimitry Andric using are_base_of = conjunction<std::is_base_of<T, Ts>...>;
1630eae32dcSDimitry Andric 
1640eae32dcSDimitry Andric namespace detail {
1650eae32dcSDimitry Andric template <typename T, typename... Us> struct TypesAreDistinct;
1660eae32dcSDimitry Andric template <typename T, typename... Us>
1670eae32dcSDimitry Andric struct TypesAreDistinct
1680eae32dcSDimitry Andric     : std::integral_constant<bool, !is_one_of<T, Us...>::value &&
1690eae32dcSDimitry Andric                                        TypesAreDistinct<Us...>::value> {};
1700eae32dcSDimitry Andric template <typename T> struct TypesAreDistinct<T> : std::true_type {};
1710eae32dcSDimitry Andric } // namespace detail
1720eae32dcSDimitry Andric 
1730eae32dcSDimitry Andric /// Determine if all types in Ts are distinct.
1740eae32dcSDimitry Andric ///
1750eae32dcSDimitry Andric /// Useful to statically assert when Ts is intended to describe a non-multi set
1760eae32dcSDimitry Andric /// of types.
1770eae32dcSDimitry Andric ///
1780eae32dcSDimitry Andric /// Expensive (currently quadratic in sizeof(Ts...)), and so should only be
1790eae32dcSDimitry Andric /// asserted once per instantiation of a type which requires it.
1800eae32dcSDimitry Andric template <typename... Ts> struct TypesAreDistinct;
1810eae32dcSDimitry Andric template <> struct TypesAreDistinct<> : std::true_type {};
1820eae32dcSDimitry Andric template <typename... Ts>
1830eae32dcSDimitry Andric struct TypesAreDistinct
1840eae32dcSDimitry Andric     : std::integral_constant<bool, detail::TypesAreDistinct<Ts...>::value> {};
1850eae32dcSDimitry Andric 
1860eae32dcSDimitry Andric /// Find the first index where a type appears in a list of types.
1870eae32dcSDimitry Andric ///
1880eae32dcSDimitry Andric /// FirstIndexOfType<T, Us...>::value is the first index of T in Us.
1890eae32dcSDimitry Andric ///
1900eae32dcSDimitry Andric /// Typically only meaningful when it is otherwise statically known that the
1910eae32dcSDimitry Andric /// type pack has no duplicate types. This should be guaranteed explicitly with
1920eae32dcSDimitry Andric /// static_assert(TypesAreDistinct<Us...>::value).
1930eae32dcSDimitry Andric ///
1940eae32dcSDimitry Andric /// It is a compile-time error to instantiate when T is not present in Us, i.e.
1950eae32dcSDimitry Andric /// if is_one_of<T, Us...>::value is false.
1960eae32dcSDimitry Andric template <typename T, typename... Us> struct FirstIndexOfType;
1970eae32dcSDimitry Andric template <typename T, typename U, typename... Us>
1980eae32dcSDimitry Andric struct FirstIndexOfType<T, U, Us...>
1990eae32dcSDimitry Andric     : std::integral_constant<size_t, 1 + FirstIndexOfType<T, Us...>::value> {};
2000eae32dcSDimitry Andric template <typename T, typename... Us>
2010eae32dcSDimitry Andric struct FirstIndexOfType<T, T, Us...> : std::integral_constant<size_t, 0> {};
2020eae32dcSDimitry Andric 
2030eae32dcSDimitry Andric /// Find the type at a given index in a list of types.
2040eae32dcSDimitry Andric ///
2050eae32dcSDimitry Andric /// TypeAtIndex<I, Ts...> is the type at index I in Ts.
2060eae32dcSDimitry Andric template <size_t I, typename... Ts>
2070eae32dcSDimitry Andric using TypeAtIndex = std::tuple_element_t<I, std::tuple<Ts...>>;
2080eae32dcSDimitry Andric 
209*81ad6265SDimitry Andric /// Helper which adds two underlying types of enumeration type.
210*81ad6265SDimitry Andric /// Implicit conversion to a common type is accepted.
211*81ad6265SDimitry Andric template <typename EnumTy1, typename EnumTy2,
212*81ad6265SDimitry Andric           typename UT1 = std::enable_if_t<std::is_enum<EnumTy1>::value,
213*81ad6265SDimitry Andric                                           std::underlying_type_t<EnumTy1>>,
214*81ad6265SDimitry Andric           typename UT2 = std::enable_if_t<std::is_enum<EnumTy2>::value,
215*81ad6265SDimitry Andric                                           std::underlying_type_t<EnumTy2>>>
216*81ad6265SDimitry Andric constexpr auto addEnumValues(EnumTy1 LHS, EnumTy2 RHS) {
217*81ad6265SDimitry Andric   return static_cast<UT1>(LHS) + static_cast<UT2>(RHS);
218*81ad6265SDimitry Andric }
219*81ad6265SDimitry Andric 
2200b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2210b57cec5SDimitry Andric //     Extra additions to <iterator>
2220b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric namespace adl_detail {
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric using std::begin;
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric template <typename ContainerTy>
2295ffd83dbSDimitry Andric decltype(auto) adl_begin(ContainerTy &&container) {
2300b57cec5SDimitry Andric   return begin(std::forward<ContainerTy>(container));
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric using std::end;
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric template <typename ContainerTy>
2365ffd83dbSDimitry Andric decltype(auto) adl_end(ContainerTy &&container) {
2370b57cec5SDimitry Andric   return end(std::forward<ContainerTy>(container));
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric using std::swap;
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric template <typename T>
2430b57cec5SDimitry Andric void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(),
2440b57cec5SDimitry Andric                                                        std::declval<T>()))) {
2450b57cec5SDimitry Andric   swap(std::forward<T>(lhs), std::forward<T>(rhs));
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric } // end namespace adl_detail
2490b57cec5SDimitry Andric 
2500b57cec5SDimitry Andric template <typename ContainerTy>
2515ffd83dbSDimitry Andric decltype(auto) adl_begin(ContainerTy &&container) {
2520b57cec5SDimitry Andric   return adl_detail::adl_begin(std::forward<ContainerTy>(container));
2530b57cec5SDimitry Andric }
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric template <typename ContainerTy>
2565ffd83dbSDimitry Andric decltype(auto) adl_end(ContainerTy &&container) {
2570b57cec5SDimitry Andric   return adl_detail::adl_end(std::forward<ContainerTy>(container));
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric template <typename T>
2610b57cec5SDimitry Andric void adl_swap(T &&lhs, T &&rhs) noexcept(
2620b57cec5SDimitry Andric     noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) {
2630b57cec5SDimitry Andric   adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs));
2640b57cec5SDimitry Andric }
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric /// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty.
2670b57cec5SDimitry Andric template <typename T>
2680b57cec5SDimitry Andric constexpr bool empty(const T &RangeOrContainer) {
2690b57cec5SDimitry Andric   return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer);
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric 
2725ffd83dbSDimitry Andric /// Returns true if the given container only contains a single element.
2735ffd83dbSDimitry Andric template <typename ContainerTy> bool hasSingleElement(ContainerTy &&C) {
2745ffd83dbSDimitry Andric   auto B = std::begin(C), E = std::end(C);
2755ffd83dbSDimitry Andric   return B != E && std::next(B) == E;
2765ffd83dbSDimitry Andric }
2775ffd83dbSDimitry Andric 
278480093f4SDimitry Andric /// Return a range covering \p RangeOrContainer with the first N elements
279480093f4SDimitry Andric /// excluded.
280e8d8bef9SDimitry Andric template <typename T> auto drop_begin(T &&RangeOrContainer, size_t N = 1) {
281480093f4SDimitry Andric   return make_range(std::next(adl_begin(RangeOrContainer), N),
282480093f4SDimitry Andric                     adl_end(RangeOrContainer));
283480093f4SDimitry Andric }
284480093f4SDimitry Andric 
285*81ad6265SDimitry Andric /// Return a range covering \p RangeOrContainer with the last N elements
286*81ad6265SDimitry Andric /// excluded.
287*81ad6265SDimitry Andric template <typename T> auto drop_end(T &&RangeOrContainer, size_t N = 1) {
288*81ad6265SDimitry Andric   return make_range(adl_begin(RangeOrContainer),
289*81ad6265SDimitry Andric                     std::prev(adl_end(RangeOrContainer), N));
290*81ad6265SDimitry Andric }
291*81ad6265SDimitry Andric 
2920b57cec5SDimitry Andric // mapped_iterator - This is a simple iterator adapter that causes a function to
2930b57cec5SDimitry Andric // be applied whenever operator* is invoked on the iterator.
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric template <typename ItTy, typename FuncTy,
296349cc55cSDimitry Andric           typename ReferenceTy =
2970b57cec5SDimitry Andric               decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))>
2980b57cec5SDimitry Andric class mapped_iterator
2990b57cec5SDimitry Andric     : public iterator_adaptor_base<
3000b57cec5SDimitry Andric           mapped_iterator<ItTy, FuncTy>, ItTy,
3010b57cec5SDimitry Andric           typename std::iterator_traits<ItTy>::iterator_category,
302349cc55cSDimitry Andric           std::remove_reference_t<ReferenceTy>,
303349cc55cSDimitry Andric           typename std::iterator_traits<ItTy>::difference_type,
304349cc55cSDimitry Andric           std::remove_reference_t<ReferenceTy> *, ReferenceTy> {
3050b57cec5SDimitry Andric public:
3060b57cec5SDimitry Andric   mapped_iterator(ItTy U, FuncTy F)
3070b57cec5SDimitry Andric     : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {}
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   ItTy getCurrent() { return this->I; }
3100b57cec5SDimitry Andric 
311349cc55cSDimitry Andric   const FuncTy &getFunction() const { return F; }
312349cc55cSDimitry Andric 
313349cc55cSDimitry Andric   ReferenceTy operator*() const { return F(*this->I); }
3140b57cec5SDimitry Andric 
3150b57cec5SDimitry Andric private:
3160b57cec5SDimitry Andric   FuncTy F;
3170b57cec5SDimitry Andric };
3180b57cec5SDimitry Andric 
3190b57cec5SDimitry Andric // map_iterator - Provide a convenient way to create mapped_iterators, just like
3200b57cec5SDimitry Andric // make_pair is useful for creating pairs...
3210b57cec5SDimitry Andric template <class ItTy, class FuncTy>
3220b57cec5SDimitry Andric inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) {
3230b57cec5SDimitry Andric   return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F));
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric template <class ContainerTy, class FuncTy>
3275ffd83dbSDimitry Andric auto map_range(ContainerTy &&C, FuncTy F) {
3280b57cec5SDimitry Andric   return make_range(map_iterator(C.begin(), F), map_iterator(C.end(), F));
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric 
331349cc55cSDimitry Andric /// A base type of mapped iterator, that is useful for building derived
332349cc55cSDimitry Andric /// iterators that do not need/want to store the map function (as in
333349cc55cSDimitry Andric /// mapped_iterator). These iterators must simply provide a `mapElement` method
334349cc55cSDimitry Andric /// that defines how to map a value of the iterator to the provided reference
335349cc55cSDimitry Andric /// type.
336349cc55cSDimitry Andric template <typename DerivedT, typename ItTy, typename ReferenceTy>
337349cc55cSDimitry Andric class mapped_iterator_base
338349cc55cSDimitry Andric     : public iterator_adaptor_base<
339349cc55cSDimitry Andric           DerivedT, ItTy,
340349cc55cSDimitry Andric           typename std::iterator_traits<ItTy>::iterator_category,
341349cc55cSDimitry Andric           std::remove_reference_t<ReferenceTy>,
342349cc55cSDimitry Andric           typename std::iterator_traits<ItTy>::difference_type,
343349cc55cSDimitry Andric           std::remove_reference_t<ReferenceTy> *, ReferenceTy> {
344349cc55cSDimitry Andric public:
345349cc55cSDimitry Andric   using BaseT = mapped_iterator_base;
346349cc55cSDimitry Andric 
347349cc55cSDimitry Andric   mapped_iterator_base(ItTy U)
348349cc55cSDimitry Andric       : mapped_iterator_base::iterator_adaptor_base(std::move(U)) {}
349349cc55cSDimitry Andric 
350349cc55cSDimitry Andric   ItTy getCurrent() { return this->I; }
351349cc55cSDimitry Andric 
352349cc55cSDimitry Andric   ReferenceTy operator*() const {
353349cc55cSDimitry Andric     return static_cast<const DerivedT &>(*this).mapElement(*this->I);
354349cc55cSDimitry Andric   }
355349cc55cSDimitry Andric };
356349cc55cSDimitry Andric 
3570b57cec5SDimitry Andric /// Helper to determine if type T has a member called rbegin().
3580b57cec5SDimitry Andric template <typename Ty> class has_rbegin_impl {
3590b57cec5SDimitry Andric   using yes = char[1];
3600b57cec5SDimitry Andric   using no = char[2];
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric   template <typename Inner>
3630b57cec5SDimitry Andric   static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr);
3640b57cec5SDimitry Andric 
3650b57cec5SDimitry Andric   template <typename>
3660b57cec5SDimitry Andric   static no& test(...);
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric public:
3690b57cec5SDimitry Andric   static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
3700b57cec5SDimitry Andric };
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric /// Metafunction to determine if T& or T has a member called rbegin().
3730b57cec5SDimitry Andric template <typename Ty>
3740b57cec5SDimitry Andric struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> {
3750b57cec5SDimitry Andric };
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric // Returns an iterator_range over the given container which iterates in reverse.
3780b57cec5SDimitry Andric // Note that the container must have rbegin()/rend() methods for this to work.
3790b57cec5SDimitry Andric template <typename ContainerTy>
3800b57cec5SDimitry Andric auto reverse(ContainerTy &&C,
3815ffd83dbSDimitry Andric              std::enable_if_t<has_rbegin<ContainerTy>::value> * = nullptr) {
3820b57cec5SDimitry Andric   return make_range(C.rbegin(), C.rend());
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric // Returns an iterator_range over the given container which iterates in reverse.
3860b57cec5SDimitry Andric // Note that the container must have begin()/end() methods which return
3870b57cec5SDimitry Andric // bidirectional iterators for this to work.
3880b57cec5SDimitry Andric template <typename ContainerTy>
3895ffd83dbSDimitry Andric auto reverse(ContainerTy &&C,
3905ffd83dbSDimitry Andric              std::enable_if_t<!has_rbegin<ContainerTy>::value> * = nullptr) {
39104eeddc0SDimitry Andric   return make_range(std::make_reverse_iterator(std::end(C)),
39204eeddc0SDimitry Andric                     std::make_reverse_iterator(std::begin(C)));
3930b57cec5SDimitry Andric }
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric /// An iterator adaptor that filters the elements of given inner iterators.
3960b57cec5SDimitry Andric ///
3970b57cec5SDimitry Andric /// The predicate parameter should be a callable object that accepts the wrapped
3980b57cec5SDimitry Andric /// iterator's reference type and returns a bool. When incrementing or
3990b57cec5SDimitry Andric /// decrementing the iterator, it will call the predicate on each element and
4000b57cec5SDimitry Andric /// skip any where it returns false.
4010b57cec5SDimitry Andric ///
4020b57cec5SDimitry Andric /// \code
4030b57cec5SDimitry Andric ///   int A[] = { 1, 2, 3, 4 };
4040b57cec5SDimitry Andric ///   auto R = make_filter_range(A, [](int N) { return N % 2 == 1; });
4050b57cec5SDimitry Andric ///   // R contains { 1, 3 }.
4060b57cec5SDimitry Andric /// \endcode
4070b57cec5SDimitry Andric ///
4080b57cec5SDimitry Andric /// Note: filter_iterator_base implements support for forward iteration.
4090b57cec5SDimitry Andric /// filter_iterator_impl exists to provide support for bidirectional iteration,
4100b57cec5SDimitry Andric /// conditional on whether the wrapped iterator supports it.
4110b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT, typename IterTag>
4120b57cec5SDimitry Andric class filter_iterator_base
4130b57cec5SDimitry Andric     : public iterator_adaptor_base<
4140b57cec5SDimitry Andric           filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
4150b57cec5SDimitry Andric           WrappedIteratorT,
4160b57cec5SDimitry Andric           typename std::common_type<
4170b57cec5SDimitry Andric               IterTag, typename std::iterator_traits<
4180b57cec5SDimitry Andric                            WrappedIteratorT>::iterator_category>::type> {
419349cc55cSDimitry Andric   using BaseT = typename filter_iterator_base::iterator_adaptor_base;
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric protected:
4220b57cec5SDimitry Andric   WrappedIteratorT End;
4230b57cec5SDimitry Andric   PredicateT Pred;
4240b57cec5SDimitry Andric 
4250b57cec5SDimitry Andric   void findNextValid() {
4260b57cec5SDimitry Andric     while (this->I != End && !Pred(*this->I))
4270b57cec5SDimitry Andric       BaseT::operator++();
4280b57cec5SDimitry Andric   }
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric   // Construct the iterator. The begin iterator needs to know where the end
4310b57cec5SDimitry Andric   // is, so that it can properly stop when it gets there. The end iterator only
4320b57cec5SDimitry Andric   // needs the predicate to support bidirectional iteration.
4330b57cec5SDimitry Andric   filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End,
4340b57cec5SDimitry Andric                        PredicateT Pred)
4350b57cec5SDimitry Andric       : BaseT(Begin), End(End), Pred(Pred) {
4360b57cec5SDimitry Andric     findNextValid();
4370b57cec5SDimitry Andric   }
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric public:
4400b57cec5SDimitry Andric   using BaseT::operator++;
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   filter_iterator_base &operator++() {
4430b57cec5SDimitry Andric     BaseT::operator++();
4440b57cec5SDimitry Andric     findNextValid();
4450b57cec5SDimitry Andric     return *this;
4460b57cec5SDimitry Andric   }
447*81ad6265SDimitry Andric 
448*81ad6265SDimitry Andric   decltype(auto) operator*() const {
449*81ad6265SDimitry Andric     assert(BaseT::wrapped() != End && "Cannot dereference end iterator!");
450*81ad6265SDimitry Andric     return BaseT::operator*();
451*81ad6265SDimitry Andric   }
452*81ad6265SDimitry Andric 
453*81ad6265SDimitry Andric   decltype(auto) operator->() const {
454*81ad6265SDimitry Andric     assert(BaseT::wrapped() != End && "Cannot dereference end iterator!");
455*81ad6265SDimitry Andric     return BaseT::operator->();
456*81ad6265SDimitry Andric   }
4570b57cec5SDimitry Andric };
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric /// Specialization of filter_iterator_base for forward iteration only.
4600b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT,
4610b57cec5SDimitry Andric           typename IterTag = std::forward_iterator_tag>
4620b57cec5SDimitry Andric class filter_iterator_impl
4630b57cec5SDimitry Andric     : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> {
4640b57cec5SDimitry Andric public:
4650b57cec5SDimitry Andric   filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
4660b57cec5SDimitry Andric                        PredicateT Pred)
467349cc55cSDimitry Andric       : filter_iterator_impl::filter_iterator_base(Begin, End, Pred) {}
4680b57cec5SDimitry Andric };
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric /// Specialization of filter_iterator_base for bidirectional iteration.
4710b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT>
4720b57cec5SDimitry Andric class filter_iterator_impl<WrappedIteratorT, PredicateT,
4730b57cec5SDimitry Andric                            std::bidirectional_iterator_tag>
4740b57cec5SDimitry Andric     : public filter_iterator_base<WrappedIteratorT, PredicateT,
4750b57cec5SDimitry Andric                                   std::bidirectional_iterator_tag> {
476349cc55cSDimitry Andric   using BaseT = typename filter_iterator_impl::filter_iterator_base;
477349cc55cSDimitry Andric 
4780b57cec5SDimitry Andric   void findPrevValid() {
4790b57cec5SDimitry Andric     while (!this->Pred(*this->I))
4800b57cec5SDimitry Andric       BaseT::operator--();
4810b57cec5SDimitry Andric   }
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric public:
4840b57cec5SDimitry Andric   using BaseT::operator--;
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric   filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
4870b57cec5SDimitry Andric                        PredicateT Pred)
4880b57cec5SDimitry Andric       : BaseT(Begin, End, Pred) {}
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric   filter_iterator_impl &operator--() {
4910b57cec5SDimitry Andric     BaseT::operator--();
4920b57cec5SDimitry Andric     findPrevValid();
4930b57cec5SDimitry Andric     return *this;
4940b57cec5SDimitry Andric   }
4950b57cec5SDimitry Andric };
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric namespace detail {
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric template <bool is_bidirectional> struct fwd_or_bidi_tag_impl {
5000b57cec5SDimitry Andric   using type = std::forward_iterator_tag;
5010b57cec5SDimitry Andric };
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric template <> struct fwd_or_bidi_tag_impl<true> {
5040b57cec5SDimitry Andric   using type = std::bidirectional_iterator_tag;
5050b57cec5SDimitry Andric };
5060b57cec5SDimitry Andric 
5070b57cec5SDimitry Andric /// Helper which sets its type member to forward_iterator_tag if the category
5080b57cec5SDimitry Andric /// of \p IterT does not derive from bidirectional_iterator_tag, and to
5090b57cec5SDimitry Andric /// bidirectional_iterator_tag otherwise.
5100b57cec5SDimitry Andric template <typename IterT> struct fwd_or_bidi_tag {
5110b57cec5SDimitry Andric   using type = typename fwd_or_bidi_tag_impl<std::is_base_of<
5120b57cec5SDimitry Andric       std::bidirectional_iterator_tag,
5130b57cec5SDimitry Andric       typename std::iterator_traits<IterT>::iterator_category>::value>::type;
5140b57cec5SDimitry Andric };
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric } // namespace detail
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric /// Defines filter_iterator to a suitable specialization of
5190b57cec5SDimitry Andric /// filter_iterator_impl, based on the underlying iterator's category.
5200b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT>
5210b57cec5SDimitry Andric using filter_iterator = filter_iterator_impl<
5220b57cec5SDimitry Andric     WrappedIteratorT, PredicateT,
5230b57cec5SDimitry Andric     typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>;
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric /// Convenience function that takes a range of elements and a predicate,
5260b57cec5SDimitry Andric /// and return a new filter_iterator range.
5270b57cec5SDimitry Andric ///
5280b57cec5SDimitry Andric /// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the
5290b57cec5SDimitry Andric /// lifetime of that temporary is not kept by the returned range object, and the
5300b57cec5SDimitry Andric /// temporary is going to be dropped on the floor after the make_iterator_range
5310b57cec5SDimitry Andric /// full expression that contains this function call.
5320b57cec5SDimitry Andric template <typename RangeT, typename PredicateT>
5330b57cec5SDimitry Andric iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>>
5340b57cec5SDimitry Andric make_filter_range(RangeT &&Range, PredicateT Pred) {
5350b57cec5SDimitry Andric   using FilterIteratorT =
5360b57cec5SDimitry Andric       filter_iterator<detail::IterOfRange<RangeT>, PredicateT>;
5370b57cec5SDimitry Andric   return make_range(
5380b57cec5SDimitry Andric       FilterIteratorT(std::begin(std::forward<RangeT>(Range)),
5390b57cec5SDimitry Andric                       std::end(std::forward<RangeT>(Range)), Pred),
5400b57cec5SDimitry Andric       FilterIteratorT(std::end(std::forward<RangeT>(Range)),
5410b57cec5SDimitry Andric                       std::end(std::forward<RangeT>(Range)), Pred));
5420b57cec5SDimitry Andric }
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric /// A pseudo-iterator adaptor that is designed to implement "early increment"
5450b57cec5SDimitry Andric /// style loops.
5460b57cec5SDimitry Andric ///
5470b57cec5SDimitry Andric /// This is *not a normal iterator* and should almost never be used directly. It
5480b57cec5SDimitry Andric /// is intended primarily to be used with range based for loops and some range
5490b57cec5SDimitry Andric /// algorithms.
5500b57cec5SDimitry Andric ///
5510b57cec5SDimitry Andric /// The iterator isn't quite an `OutputIterator` or an `InputIterator` but
5520b57cec5SDimitry Andric /// somewhere between them. The constraints of these iterators are:
5530b57cec5SDimitry Andric ///
5540b57cec5SDimitry Andric /// - On construction or after being incremented, it is comparable and
5550b57cec5SDimitry Andric ///   dereferencable. It is *not* incrementable.
5560b57cec5SDimitry Andric /// - After being dereferenced, it is neither comparable nor dereferencable, it
5570b57cec5SDimitry Andric ///   is only incrementable.
5580b57cec5SDimitry Andric ///
5590b57cec5SDimitry Andric /// This means you can only dereference the iterator once, and you can only
5600b57cec5SDimitry Andric /// increment it once between dereferences.
5610b57cec5SDimitry Andric template <typename WrappedIteratorT>
5620b57cec5SDimitry Andric class early_inc_iterator_impl
5630b57cec5SDimitry Andric     : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
5640b57cec5SDimitry Andric                                    WrappedIteratorT, std::input_iterator_tag> {
565349cc55cSDimitry Andric   using BaseT = typename early_inc_iterator_impl::iterator_adaptor_base;
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric   using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer;
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric protected:
5700b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS
5710b57cec5SDimitry Andric   bool IsEarlyIncremented = false;
5720b57cec5SDimitry Andric #endif
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric public:
5750b57cec5SDimitry Andric   early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {}
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric   using BaseT::operator*;
578e8d8bef9SDimitry Andric   decltype(*std::declval<WrappedIteratorT>()) operator*() {
5790b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS
5800b57cec5SDimitry Andric     assert(!IsEarlyIncremented && "Cannot dereference twice!");
5810b57cec5SDimitry Andric     IsEarlyIncremented = true;
5820b57cec5SDimitry Andric #endif
5830b57cec5SDimitry Andric     return *(this->I)++;
5840b57cec5SDimitry Andric   }
5850b57cec5SDimitry Andric 
5860b57cec5SDimitry Andric   using BaseT::operator++;
5870b57cec5SDimitry Andric   early_inc_iterator_impl &operator++() {
5880b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS
5890b57cec5SDimitry Andric     assert(IsEarlyIncremented && "Cannot increment before dereferencing!");
5900b57cec5SDimitry Andric     IsEarlyIncremented = false;
5910b57cec5SDimitry Andric #endif
5920b57cec5SDimitry Andric     return *this;
5930b57cec5SDimitry Andric   }
5940b57cec5SDimitry Andric 
595e8d8bef9SDimitry Andric   friend bool operator==(const early_inc_iterator_impl &LHS,
596e8d8bef9SDimitry Andric                          const early_inc_iterator_impl &RHS) {
5970b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS
598e8d8bef9SDimitry Andric     assert(!LHS.IsEarlyIncremented && "Cannot compare after dereferencing!");
5990b57cec5SDimitry Andric #endif
600e8d8bef9SDimitry Andric     return (const BaseT &)LHS == (const BaseT &)RHS;
6010b57cec5SDimitry Andric   }
6020b57cec5SDimitry Andric };
6030b57cec5SDimitry Andric 
6040b57cec5SDimitry Andric /// Make a range that does early increment to allow mutation of the underlying
6050b57cec5SDimitry Andric /// range without disrupting iteration.
6060b57cec5SDimitry Andric ///
6070b57cec5SDimitry Andric /// The underlying iterator will be incremented immediately after it is
6080b57cec5SDimitry Andric /// dereferenced, allowing deletion of the current node or insertion of nodes to
6090b57cec5SDimitry Andric /// not disrupt iteration provided they do not invalidate the *next* iterator --
6100b57cec5SDimitry Andric /// the current iterator can be invalidated.
6110b57cec5SDimitry Andric ///
6120b57cec5SDimitry Andric /// This requires a very exact pattern of use that is only really suitable to
6130b57cec5SDimitry Andric /// range based for loops and other range algorithms that explicitly guarantee
6140b57cec5SDimitry Andric /// to dereference exactly once each element, and to increment exactly once each
6150b57cec5SDimitry Andric /// element.
6160b57cec5SDimitry Andric template <typename RangeT>
6170b57cec5SDimitry Andric iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>>
6180b57cec5SDimitry Andric make_early_inc_range(RangeT &&Range) {
6190b57cec5SDimitry Andric   using EarlyIncIteratorT =
6200b57cec5SDimitry Andric       early_inc_iterator_impl<detail::IterOfRange<RangeT>>;
6210b57cec5SDimitry Andric   return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))),
6220b57cec5SDimitry Andric                     EarlyIncIteratorT(std::end(std::forward<RangeT>(Range))));
6230b57cec5SDimitry Andric }
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric // forward declarations required by zip_shortest/zip_first/zip_longest
6260b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
6270b57cec5SDimitry Andric bool all_of(R &&range, UnaryPredicate P);
6280b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
6290b57cec5SDimitry Andric bool any_of(R &&range, UnaryPredicate P);
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric namespace detail {
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric using std::declval;
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric // We have to alias this since inlining the actual type at the usage site
6360b57cec5SDimitry Andric // in the parameter list of iterator_facade_base<> below ICEs MSVC 2017.
6370b57cec5SDimitry Andric template<typename... Iters> struct ZipTupleType {
6380b57cec5SDimitry Andric   using type = std::tuple<decltype(*declval<Iters>())...>;
6390b57cec5SDimitry Andric };
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric template <typename ZipType, typename... Iters>
6420b57cec5SDimitry Andric using zip_traits = iterator_facade_base<
6430b57cec5SDimitry Andric     ZipType, typename std::common_type<std::bidirectional_iterator_tag,
6440b57cec5SDimitry Andric                                        typename std::iterator_traits<
6450b57cec5SDimitry Andric                                            Iters>::iterator_category...>::type,
6460b57cec5SDimitry Andric     // ^ TODO: Implement random access methods.
6470b57cec5SDimitry Andric     typename ZipTupleType<Iters...>::type,
6480b57cec5SDimitry Andric     typename std::iterator_traits<typename std::tuple_element<
6490b57cec5SDimitry Andric         0, std::tuple<Iters...>>::type>::difference_type,
6500b57cec5SDimitry Andric     // ^ FIXME: This follows boost::make_zip_iterator's assumption that all
6510b57cec5SDimitry Andric     // inner iterators have the same difference_type. It would fail if, for
6520b57cec5SDimitry Andric     // instance, the second field's difference_type were non-numeric while the
6530b57cec5SDimitry Andric     // first is.
6540b57cec5SDimitry Andric     typename ZipTupleType<Iters...>::type *,
6550b57cec5SDimitry Andric     typename ZipTupleType<Iters...>::type>;
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric template <typename ZipType, typename... Iters>
6580b57cec5SDimitry Andric struct zip_common : public zip_traits<ZipType, Iters...> {
6590b57cec5SDimitry Andric   using Base = zip_traits<ZipType, Iters...>;
6600b57cec5SDimitry Andric   using value_type = typename Base::value_type;
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric   std::tuple<Iters...> iterators;
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric protected:
6658bcb0991SDimitry Andric   template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const {
6660b57cec5SDimitry Andric     return value_type(*std::get<Ns>(iterators)...);
6670b57cec5SDimitry Andric   }
6680b57cec5SDimitry Andric 
6690b57cec5SDimitry Andric   template <size_t... Ns>
6708bcb0991SDimitry Andric   decltype(iterators) tup_inc(std::index_sequence<Ns...>) const {
6710b57cec5SDimitry Andric     return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...);
6720b57cec5SDimitry Andric   }
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric   template <size_t... Ns>
6758bcb0991SDimitry Andric   decltype(iterators) tup_dec(std::index_sequence<Ns...>) const {
6760b57cec5SDimitry Andric     return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...);
6770b57cec5SDimitry Andric   }
6780b57cec5SDimitry Andric 
679349cc55cSDimitry Andric   template <size_t... Ns>
680349cc55cSDimitry Andric   bool test_all_equals(const zip_common &other,
681349cc55cSDimitry Andric             std::index_sequence<Ns...>) const {
682349cc55cSDimitry Andric     return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) ==
683349cc55cSDimitry Andric                                               std::get<Ns>(other.iterators)...},
684349cc55cSDimitry Andric                   identity<bool>{});
685349cc55cSDimitry Andric   }
686349cc55cSDimitry Andric 
6870b57cec5SDimitry Andric public:
6880b57cec5SDimitry Andric   zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {}
6890b57cec5SDimitry Andric 
690349cc55cSDimitry Andric   value_type operator*() const {
6918bcb0991SDimitry Andric     return deref(std::index_sequence_for<Iters...>{});
6920b57cec5SDimitry Andric   }
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric   ZipType &operator++() {
6958bcb0991SDimitry Andric     iterators = tup_inc(std::index_sequence_for<Iters...>{});
6960b57cec5SDimitry Andric     return *reinterpret_cast<ZipType *>(this);
6970b57cec5SDimitry Andric   }
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric   ZipType &operator--() {
7000b57cec5SDimitry Andric     static_assert(Base::IsBidirectional,
7010b57cec5SDimitry Andric                   "All inner iterators must be at least bidirectional.");
7028bcb0991SDimitry Andric     iterators = tup_dec(std::index_sequence_for<Iters...>{});
7030b57cec5SDimitry Andric     return *reinterpret_cast<ZipType *>(this);
7040b57cec5SDimitry Andric   }
705349cc55cSDimitry Andric 
706349cc55cSDimitry Andric   /// Return true if all the iterator are matching `other`'s iterators.
707349cc55cSDimitry Andric   bool all_equals(zip_common &other) {
708349cc55cSDimitry Andric     return test_all_equals(other, std::index_sequence_for<Iters...>{});
709349cc55cSDimitry Andric   }
7100b57cec5SDimitry Andric };
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric template <typename... Iters>
7130b57cec5SDimitry Andric struct zip_first : public zip_common<zip_first<Iters...>, Iters...> {
7140b57cec5SDimitry Andric   using Base = zip_common<zip_first<Iters...>, Iters...>;
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric   bool operator==(const zip_first<Iters...> &other) const {
7170b57cec5SDimitry Andric     return std::get<0>(this->iterators) == std::get<0>(other.iterators);
7180b57cec5SDimitry Andric   }
7190b57cec5SDimitry Andric 
7200b57cec5SDimitry Andric   zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
7210b57cec5SDimitry Andric };
7220b57cec5SDimitry Andric 
7230b57cec5SDimitry Andric template <typename... Iters>
7240b57cec5SDimitry Andric class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> {
7250b57cec5SDimitry Andric   template <size_t... Ns>
7268bcb0991SDimitry Andric   bool test(const zip_shortest<Iters...> &other,
7278bcb0991SDimitry Andric             std::index_sequence<Ns...>) const {
7280b57cec5SDimitry Andric     return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
7290b57cec5SDimitry Andric                                               std::get<Ns>(other.iterators)...},
7300b57cec5SDimitry Andric                   identity<bool>{});
7310b57cec5SDimitry Andric   }
7320b57cec5SDimitry Andric 
7330b57cec5SDimitry Andric public:
7340b57cec5SDimitry Andric   using Base = zip_common<zip_shortest<Iters...>, Iters...>;
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric   zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   bool operator==(const zip_shortest<Iters...> &other) const {
7398bcb0991SDimitry Andric     return !test(other, std::index_sequence_for<Iters...>{});
7400b57cec5SDimitry Andric   }
7410b57cec5SDimitry Andric };
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric template <template <typename...> class ItType, typename... Args> class zippy {
7440b57cec5SDimitry Andric public:
7450b57cec5SDimitry Andric   using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>;
7460b57cec5SDimitry Andric   using iterator_category = typename iterator::iterator_category;
7470b57cec5SDimitry Andric   using value_type = typename iterator::value_type;
7480b57cec5SDimitry Andric   using difference_type = typename iterator::difference_type;
7490b57cec5SDimitry Andric   using pointer = typename iterator::pointer;
7500b57cec5SDimitry Andric   using reference = typename iterator::reference;
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric private:
7530b57cec5SDimitry Andric   std::tuple<Args...> ts;
7540b57cec5SDimitry Andric 
7558bcb0991SDimitry Andric   template <size_t... Ns>
7568bcb0991SDimitry Andric   iterator begin_impl(std::index_sequence<Ns...>) const {
7570b57cec5SDimitry Andric     return iterator(std::begin(std::get<Ns>(ts))...);
7580b57cec5SDimitry Andric   }
7598bcb0991SDimitry Andric   template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const {
7600b57cec5SDimitry Andric     return iterator(std::end(std::get<Ns>(ts))...);
7610b57cec5SDimitry Andric   }
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric public:
7640b57cec5SDimitry Andric   zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
7650b57cec5SDimitry Andric 
7668bcb0991SDimitry Andric   iterator begin() const {
7678bcb0991SDimitry Andric     return begin_impl(std::index_sequence_for<Args...>{});
7688bcb0991SDimitry Andric   }
7698bcb0991SDimitry Andric   iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); }
7700b57cec5SDimitry Andric };
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric } // end namespace detail
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric /// zip iterator for two or more iteratable types.
7750b57cec5SDimitry Andric template <typename T, typename U, typename... Args>
7760b57cec5SDimitry Andric detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u,
7770b57cec5SDimitry Andric                                                        Args &&... args) {
7780b57cec5SDimitry Andric   return detail::zippy<detail::zip_shortest, T, U, Args...>(
7790b57cec5SDimitry Andric       std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
7800b57cec5SDimitry Andric }
7810b57cec5SDimitry Andric 
7820b57cec5SDimitry Andric /// zip iterator that, for the sake of efficiency, assumes the first iteratee to
7830b57cec5SDimitry Andric /// be the shortest.
7840b57cec5SDimitry Andric template <typename T, typename U, typename... Args>
7850b57cec5SDimitry Andric detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u,
7860b57cec5SDimitry Andric                                                           Args &&... args) {
7870b57cec5SDimitry Andric   return detail::zippy<detail::zip_first, T, U, Args...>(
7880b57cec5SDimitry Andric       std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
7890b57cec5SDimitry Andric }
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric namespace detail {
7920b57cec5SDimitry Andric template <typename Iter>
7935ffd83dbSDimitry Andric Iter next_or_end(const Iter &I, const Iter &End) {
7940b57cec5SDimitry Andric   if (I == End)
7950b57cec5SDimitry Andric     return End;
7960b57cec5SDimitry Andric   return std::next(I);
7970b57cec5SDimitry Andric }
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric template <typename Iter>
8005ffd83dbSDimitry Andric auto deref_or_none(const Iter &I, const Iter &End) -> llvm::Optional<
8015ffd83dbSDimitry Andric     std::remove_const_t<std::remove_reference_t<decltype(*I)>>> {
8020b57cec5SDimitry Andric   if (I == End)
8030b57cec5SDimitry Andric     return None;
8040b57cec5SDimitry Andric   return *I;
8050b57cec5SDimitry Andric }
8060b57cec5SDimitry Andric 
8070b57cec5SDimitry Andric template <typename Iter> struct ZipLongestItemType {
8080b57cec5SDimitry Andric   using type =
8090b57cec5SDimitry Andric       llvm::Optional<typename std::remove_const<typename std::remove_reference<
8100b57cec5SDimitry Andric           decltype(*std::declval<Iter>())>::type>::type>;
8110b57cec5SDimitry Andric };
8120b57cec5SDimitry Andric 
8130b57cec5SDimitry Andric template <typename... Iters> struct ZipLongestTupleType {
8140b57cec5SDimitry Andric   using type = std::tuple<typename ZipLongestItemType<Iters>::type...>;
8150b57cec5SDimitry Andric };
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric template <typename... Iters>
8180b57cec5SDimitry Andric class zip_longest_iterator
8190b57cec5SDimitry Andric     : public iterator_facade_base<
8200b57cec5SDimitry Andric           zip_longest_iterator<Iters...>,
8210b57cec5SDimitry Andric           typename std::common_type<
8220b57cec5SDimitry Andric               std::forward_iterator_tag,
8230b57cec5SDimitry Andric               typename std::iterator_traits<Iters>::iterator_category...>::type,
8240b57cec5SDimitry Andric           typename ZipLongestTupleType<Iters...>::type,
8250b57cec5SDimitry Andric           typename std::iterator_traits<typename std::tuple_element<
8260b57cec5SDimitry Andric               0, std::tuple<Iters...>>::type>::difference_type,
8270b57cec5SDimitry Andric           typename ZipLongestTupleType<Iters...>::type *,
8280b57cec5SDimitry Andric           typename ZipLongestTupleType<Iters...>::type> {
8290b57cec5SDimitry Andric public:
8300b57cec5SDimitry Andric   using value_type = typename ZipLongestTupleType<Iters...>::type;
8310b57cec5SDimitry Andric 
8320b57cec5SDimitry Andric private:
8330b57cec5SDimitry Andric   std::tuple<Iters...> iterators;
8340b57cec5SDimitry Andric   std::tuple<Iters...> end_iterators;
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric   template <size_t... Ns>
8370b57cec5SDimitry Andric   bool test(const zip_longest_iterator<Iters...> &other,
8388bcb0991SDimitry Andric             std::index_sequence<Ns...>) const {
8390b57cec5SDimitry Andric     return llvm::any_of(
8400b57cec5SDimitry Andric         std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
8410b57cec5SDimitry Andric                                     std::get<Ns>(other.iterators)...},
8420b57cec5SDimitry Andric         identity<bool>{});
8430b57cec5SDimitry Andric   }
8440b57cec5SDimitry Andric 
8458bcb0991SDimitry Andric   template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const {
8460b57cec5SDimitry Andric     return value_type(
8470b57cec5SDimitry Andric         deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
8480b57cec5SDimitry Andric   }
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric   template <size_t... Ns>
8518bcb0991SDimitry Andric   decltype(iterators) tup_inc(std::index_sequence<Ns...>) const {
8520b57cec5SDimitry Andric     return std::tuple<Iters...>(
8530b57cec5SDimitry Andric         next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
8540b57cec5SDimitry Andric   }
8550b57cec5SDimitry Andric 
8560b57cec5SDimitry Andric public:
8570b57cec5SDimitry Andric   zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts)
8580b57cec5SDimitry Andric       : iterators(std::forward<Iters>(ts.first)...),
8590b57cec5SDimitry Andric         end_iterators(std::forward<Iters>(ts.second)...) {}
8600b57cec5SDimitry Andric 
8618bcb0991SDimitry Andric   value_type operator*() const {
8628bcb0991SDimitry Andric     return deref(std::index_sequence_for<Iters...>{});
8638bcb0991SDimitry Andric   }
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric   zip_longest_iterator<Iters...> &operator++() {
8668bcb0991SDimitry Andric     iterators = tup_inc(std::index_sequence_for<Iters...>{});
8670b57cec5SDimitry Andric     return *this;
8680b57cec5SDimitry Andric   }
8690b57cec5SDimitry Andric 
8700b57cec5SDimitry Andric   bool operator==(const zip_longest_iterator<Iters...> &other) const {
8718bcb0991SDimitry Andric     return !test(other, std::index_sequence_for<Iters...>{});
8720b57cec5SDimitry Andric   }
8730b57cec5SDimitry Andric };
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric template <typename... Args> class zip_longest_range {
8760b57cec5SDimitry Andric public:
8770b57cec5SDimitry Andric   using iterator =
8780b57cec5SDimitry Andric       zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>;
8790b57cec5SDimitry Andric   using iterator_category = typename iterator::iterator_category;
8800b57cec5SDimitry Andric   using value_type = typename iterator::value_type;
8810b57cec5SDimitry Andric   using difference_type = typename iterator::difference_type;
8820b57cec5SDimitry Andric   using pointer = typename iterator::pointer;
8830b57cec5SDimitry Andric   using reference = typename iterator::reference;
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric private:
8860b57cec5SDimitry Andric   std::tuple<Args...> ts;
8870b57cec5SDimitry Andric 
8888bcb0991SDimitry Andric   template <size_t... Ns>
8898bcb0991SDimitry Andric   iterator begin_impl(std::index_sequence<Ns...>) const {
8900b57cec5SDimitry Andric     return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)),
8910b57cec5SDimitry Andric                                    adl_end(std::get<Ns>(ts)))...);
8920b57cec5SDimitry Andric   }
8930b57cec5SDimitry Andric 
8948bcb0991SDimitry Andric   template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const {
8950b57cec5SDimitry Andric     return iterator(std::make_pair(adl_end(std::get<Ns>(ts)),
8960b57cec5SDimitry Andric                                    adl_end(std::get<Ns>(ts)))...);
8970b57cec5SDimitry Andric   }
8980b57cec5SDimitry Andric 
8990b57cec5SDimitry Andric public:
9000b57cec5SDimitry Andric   zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
9010b57cec5SDimitry Andric 
9028bcb0991SDimitry Andric   iterator begin() const {
9038bcb0991SDimitry Andric     return begin_impl(std::index_sequence_for<Args...>{});
9048bcb0991SDimitry Andric   }
9058bcb0991SDimitry Andric   iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); }
9060b57cec5SDimitry Andric };
9070b57cec5SDimitry Andric } // namespace detail
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric /// Iterate over two or more iterators at the same time. Iteration continues
9100b57cec5SDimitry Andric /// until all iterators reach the end. The llvm::Optional only contains a value
9110b57cec5SDimitry Andric /// if the iterator has not reached the end.
9120b57cec5SDimitry Andric template <typename T, typename U, typename... Args>
9130b57cec5SDimitry Andric detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u,
9140b57cec5SDimitry Andric                                                      Args &&... args) {
9150b57cec5SDimitry Andric   return detail::zip_longest_range<T, U, Args...>(
9160b57cec5SDimitry Andric       std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
9170b57cec5SDimitry Andric }
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric /// Iterator wrapper that concatenates sequences together.
9200b57cec5SDimitry Andric ///
9210b57cec5SDimitry Andric /// This can concatenate different iterators, even with different types, into
9220b57cec5SDimitry Andric /// a single iterator provided the value types of all the concatenated
9230b57cec5SDimitry Andric /// iterators expose `reference` and `pointer` types that can be converted to
9240b57cec5SDimitry Andric /// `ValueT &` and `ValueT *` respectively. It doesn't support more
9250b57cec5SDimitry Andric /// interesting/customized pointer or reference types.
9260b57cec5SDimitry Andric ///
9270b57cec5SDimitry Andric /// Currently this only supports forward or higher iterator categories as
9280b57cec5SDimitry Andric /// inputs and always exposes a forward iterator interface.
9290b57cec5SDimitry Andric template <typename ValueT, typename... IterTs>
9300b57cec5SDimitry Andric class concat_iterator
9310b57cec5SDimitry Andric     : public iterator_facade_base<concat_iterator<ValueT, IterTs...>,
9320b57cec5SDimitry Andric                                   std::forward_iterator_tag, ValueT> {
9330b57cec5SDimitry Andric   using BaseT = typename concat_iterator::iterator_facade_base;
9340b57cec5SDimitry Andric 
9350b57cec5SDimitry Andric   /// We store both the current and end iterators for each concatenated
9360b57cec5SDimitry Andric   /// sequence in a tuple of pairs.
9370b57cec5SDimitry Andric   ///
9380b57cec5SDimitry Andric   /// Note that something like iterator_range seems nice at first here, but the
9390b57cec5SDimitry Andric   /// range properties are of little benefit and end up getting in the way
9400b57cec5SDimitry Andric   /// because we need to do mutation on the current iterators.
9410b57cec5SDimitry Andric   std::tuple<IterTs...> Begins;
9420b57cec5SDimitry Andric   std::tuple<IterTs...> Ends;
9430b57cec5SDimitry Andric 
9440b57cec5SDimitry Andric   /// Attempts to increment a specific iterator.
9450b57cec5SDimitry Andric   ///
9460b57cec5SDimitry Andric   /// Returns true if it was able to increment the iterator. Returns false if
9470b57cec5SDimitry Andric   /// the iterator is already at the end iterator.
9480b57cec5SDimitry Andric   template <size_t Index> bool incrementHelper() {
9490b57cec5SDimitry Andric     auto &Begin = std::get<Index>(Begins);
9500b57cec5SDimitry Andric     auto &End = std::get<Index>(Ends);
9510b57cec5SDimitry Andric     if (Begin == End)
9520b57cec5SDimitry Andric       return false;
9530b57cec5SDimitry Andric 
9540b57cec5SDimitry Andric     ++Begin;
9550b57cec5SDimitry Andric     return true;
9560b57cec5SDimitry Andric   }
9570b57cec5SDimitry Andric 
9580b57cec5SDimitry Andric   /// Increments the first non-end iterator.
9590b57cec5SDimitry Andric   ///
9600b57cec5SDimitry Andric   /// It is an error to call this with all iterators at the end.
9618bcb0991SDimitry Andric   template <size_t... Ns> void increment(std::index_sequence<Ns...>) {
9620b57cec5SDimitry Andric     // Build a sequence of functions to increment each iterator if possible.
9630b57cec5SDimitry Andric     bool (concat_iterator::*IncrementHelperFns[])() = {
9640b57cec5SDimitry Andric         &concat_iterator::incrementHelper<Ns>...};
9650b57cec5SDimitry Andric 
9660b57cec5SDimitry Andric     // Loop over them, and stop as soon as we succeed at incrementing one.
9670b57cec5SDimitry Andric     for (auto &IncrementHelperFn : IncrementHelperFns)
9680b57cec5SDimitry Andric       if ((this->*IncrementHelperFn)())
9690b57cec5SDimitry Andric         return;
9700b57cec5SDimitry Andric 
9710b57cec5SDimitry Andric     llvm_unreachable("Attempted to increment an end concat iterator!");
9720b57cec5SDimitry Andric   }
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric   /// Returns null if the specified iterator is at the end. Otherwise,
9750b57cec5SDimitry Andric   /// dereferences the iterator and returns the address of the resulting
9760b57cec5SDimitry Andric   /// reference.
9770b57cec5SDimitry Andric   template <size_t Index> ValueT *getHelper() const {
9780b57cec5SDimitry Andric     auto &Begin = std::get<Index>(Begins);
9790b57cec5SDimitry Andric     auto &End = std::get<Index>(Ends);
9800b57cec5SDimitry Andric     if (Begin == End)
9810b57cec5SDimitry Andric       return nullptr;
9820b57cec5SDimitry Andric 
9830b57cec5SDimitry Andric     return &*Begin;
9840b57cec5SDimitry Andric   }
9850b57cec5SDimitry Andric 
9860b57cec5SDimitry Andric   /// Finds the first non-end iterator, dereferences, and returns the resulting
9870b57cec5SDimitry Andric   /// reference.
9880b57cec5SDimitry Andric   ///
9890b57cec5SDimitry Andric   /// It is an error to call this with all iterators at the end.
9908bcb0991SDimitry Andric   template <size_t... Ns> ValueT &get(std::index_sequence<Ns...>) const {
9910b57cec5SDimitry Andric     // Build a sequence of functions to get from iterator if possible.
9920b57cec5SDimitry Andric     ValueT *(concat_iterator::*GetHelperFns[])() const = {
9930b57cec5SDimitry Andric         &concat_iterator::getHelper<Ns>...};
9940b57cec5SDimitry Andric 
9950b57cec5SDimitry Andric     // Loop over them, and return the first result we find.
9960b57cec5SDimitry Andric     for (auto &GetHelperFn : GetHelperFns)
9970b57cec5SDimitry Andric       if (ValueT *P = (this->*GetHelperFn)())
9980b57cec5SDimitry Andric         return *P;
9990b57cec5SDimitry Andric 
10000b57cec5SDimitry Andric     llvm_unreachable("Attempted to get a pointer from an end concat iterator!");
10010b57cec5SDimitry Andric   }
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric public:
10045ffd83dbSDimitry Andric   /// Constructs an iterator from a sequence of ranges.
10050b57cec5SDimitry Andric   ///
10060b57cec5SDimitry Andric   /// We need the full range to know how to switch between each of the
10070b57cec5SDimitry Andric   /// iterators.
10080b57cec5SDimitry Andric   template <typename... RangeTs>
10090b57cec5SDimitry Andric   explicit concat_iterator(RangeTs &&... Ranges)
10100b57cec5SDimitry Andric       : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {}
10110b57cec5SDimitry Andric 
10120b57cec5SDimitry Andric   using BaseT::operator++;
10130b57cec5SDimitry Andric 
10140b57cec5SDimitry Andric   concat_iterator &operator++() {
10158bcb0991SDimitry Andric     increment(std::index_sequence_for<IterTs...>());
10160b57cec5SDimitry Andric     return *this;
10170b57cec5SDimitry Andric   }
10180b57cec5SDimitry Andric 
10198bcb0991SDimitry Andric   ValueT &operator*() const {
10208bcb0991SDimitry Andric     return get(std::index_sequence_for<IterTs...>());
10218bcb0991SDimitry Andric   }
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   bool operator==(const concat_iterator &RHS) const {
10240b57cec5SDimitry Andric     return Begins == RHS.Begins && Ends == RHS.Ends;
10250b57cec5SDimitry Andric   }
10260b57cec5SDimitry Andric };
10270b57cec5SDimitry Andric 
10280b57cec5SDimitry Andric namespace detail {
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric /// Helper to store a sequence of ranges being concatenated and access them.
10310b57cec5SDimitry Andric ///
10320b57cec5SDimitry Andric /// This is designed to facilitate providing actual storage when temporaries
10330b57cec5SDimitry Andric /// are passed into the constructor such that we can use it as part of range
10340b57cec5SDimitry Andric /// based for loops.
10350b57cec5SDimitry Andric template <typename ValueT, typename... RangeTs> class concat_range {
10360b57cec5SDimitry Andric public:
10370b57cec5SDimitry Andric   using iterator =
10380b57cec5SDimitry Andric       concat_iterator<ValueT,
10390b57cec5SDimitry Andric                       decltype(std::begin(std::declval<RangeTs &>()))...>;
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric private:
10420b57cec5SDimitry Andric   std::tuple<RangeTs...> Ranges;
10430b57cec5SDimitry Andric 
10444824e7fdSDimitry Andric   template <size_t... Ns>
10454824e7fdSDimitry Andric   iterator begin_impl(std::index_sequence<Ns...>) {
10464824e7fdSDimitry Andric     return iterator(std::get<Ns>(Ranges)...);
10474824e7fdSDimitry Andric   }
10484824e7fdSDimitry Andric   template <size_t... Ns>
10494824e7fdSDimitry Andric   iterator begin_impl(std::index_sequence<Ns...>) const {
10500b57cec5SDimitry Andric     return iterator(std::get<Ns>(Ranges)...);
10510b57cec5SDimitry Andric   }
10528bcb0991SDimitry Andric   template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) {
10530b57cec5SDimitry Andric     return iterator(make_range(std::end(std::get<Ns>(Ranges)),
10540b57cec5SDimitry Andric                                std::end(std::get<Ns>(Ranges)))...);
10550b57cec5SDimitry Andric   }
10564824e7fdSDimitry Andric   template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const {
10574824e7fdSDimitry Andric     return iterator(make_range(std::end(std::get<Ns>(Ranges)),
10584824e7fdSDimitry Andric                                std::end(std::get<Ns>(Ranges)))...);
10594824e7fdSDimitry Andric   }
10600b57cec5SDimitry Andric 
10610b57cec5SDimitry Andric public:
10620b57cec5SDimitry Andric   concat_range(RangeTs &&... Ranges)
10630b57cec5SDimitry Andric       : Ranges(std::forward<RangeTs>(Ranges)...) {}
10640b57cec5SDimitry Andric 
10654824e7fdSDimitry Andric   iterator begin() {
10664824e7fdSDimitry Andric     return begin_impl(std::index_sequence_for<RangeTs...>{});
10674824e7fdSDimitry Andric   }
10684824e7fdSDimitry Andric   iterator begin() const {
10694824e7fdSDimitry Andric     return begin_impl(std::index_sequence_for<RangeTs...>{});
10704824e7fdSDimitry Andric   }
10714824e7fdSDimitry Andric   iterator end() {
10724824e7fdSDimitry Andric     return end_impl(std::index_sequence_for<RangeTs...>{});
10734824e7fdSDimitry Andric   }
10744824e7fdSDimitry Andric   iterator end() const {
10754824e7fdSDimitry Andric     return end_impl(std::index_sequence_for<RangeTs...>{});
10764824e7fdSDimitry Andric   }
10770b57cec5SDimitry Andric };
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric } // end namespace detail
10800b57cec5SDimitry Andric 
10810b57cec5SDimitry Andric /// Concatenated range across two or more ranges.
10820b57cec5SDimitry Andric ///
10830b57cec5SDimitry Andric /// The desired value type must be explicitly specified.
10840b57cec5SDimitry Andric template <typename ValueT, typename... RangeTs>
10850b57cec5SDimitry Andric detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) {
10860b57cec5SDimitry Andric   static_assert(sizeof...(RangeTs) > 1,
10870b57cec5SDimitry Andric                 "Need more than one range to concatenate!");
10880b57cec5SDimitry Andric   return detail::concat_range<ValueT, RangeTs...>(
10890b57cec5SDimitry Andric       std::forward<RangeTs>(Ranges)...);
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric 
10925ffd83dbSDimitry Andric /// A utility class used to implement an iterator that contains some base object
10935ffd83dbSDimitry Andric /// and an index. The iterator moves the index but keeps the base constant.
10945ffd83dbSDimitry Andric template <typename DerivedT, typename BaseT, typename T,
10955ffd83dbSDimitry Andric           typename PointerT = T *, typename ReferenceT = T &>
10965ffd83dbSDimitry Andric class indexed_accessor_iterator
10975ffd83dbSDimitry Andric     : public llvm::iterator_facade_base<DerivedT,
10985ffd83dbSDimitry Andric                                         std::random_access_iterator_tag, T,
10995ffd83dbSDimitry Andric                                         std::ptrdiff_t, PointerT, ReferenceT> {
11005ffd83dbSDimitry Andric public:
11015ffd83dbSDimitry Andric   ptrdiff_t operator-(const indexed_accessor_iterator &rhs) const {
11025ffd83dbSDimitry Andric     assert(base == rhs.base && "incompatible iterators");
11035ffd83dbSDimitry Andric     return index - rhs.index;
11045ffd83dbSDimitry Andric   }
11055ffd83dbSDimitry Andric   bool operator==(const indexed_accessor_iterator &rhs) const {
11065ffd83dbSDimitry Andric     return base == rhs.base && index == rhs.index;
11075ffd83dbSDimitry Andric   }
11085ffd83dbSDimitry Andric   bool operator<(const indexed_accessor_iterator &rhs) const {
11095ffd83dbSDimitry Andric     assert(base == rhs.base && "incompatible iterators");
11105ffd83dbSDimitry Andric     return index < rhs.index;
11115ffd83dbSDimitry Andric   }
11125ffd83dbSDimitry Andric 
11135ffd83dbSDimitry Andric   DerivedT &operator+=(ptrdiff_t offset) {
11145ffd83dbSDimitry Andric     this->index += offset;
11155ffd83dbSDimitry Andric     return static_cast<DerivedT &>(*this);
11165ffd83dbSDimitry Andric   }
11175ffd83dbSDimitry Andric   DerivedT &operator-=(ptrdiff_t offset) {
11185ffd83dbSDimitry Andric     this->index -= offset;
11195ffd83dbSDimitry Andric     return static_cast<DerivedT &>(*this);
11205ffd83dbSDimitry Andric   }
11215ffd83dbSDimitry Andric 
11225ffd83dbSDimitry Andric   /// Returns the current index of the iterator.
11235ffd83dbSDimitry Andric   ptrdiff_t getIndex() const { return index; }
11245ffd83dbSDimitry Andric 
11255ffd83dbSDimitry Andric   /// Returns the current base of the iterator.
11265ffd83dbSDimitry Andric   const BaseT &getBase() const { return base; }
11275ffd83dbSDimitry Andric 
11285ffd83dbSDimitry Andric protected:
11295ffd83dbSDimitry Andric   indexed_accessor_iterator(BaseT base, ptrdiff_t index)
11305ffd83dbSDimitry Andric       : base(base), index(index) {}
11315ffd83dbSDimitry Andric   BaseT base;
11325ffd83dbSDimitry Andric   ptrdiff_t index;
11335ffd83dbSDimitry Andric };
11345ffd83dbSDimitry Andric 
11355ffd83dbSDimitry Andric namespace detail {
11365ffd83dbSDimitry Andric /// The class represents the base of a range of indexed_accessor_iterators. It
11375ffd83dbSDimitry Andric /// provides support for many different range functionalities, e.g.
11385ffd83dbSDimitry Andric /// drop_front/slice/etc.. Derived range classes must implement the following
11395ffd83dbSDimitry Andric /// static methods:
11405ffd83dbSDimitry Andric ///   * ReferenceT dereference_iterator(const BaseT &base, ptrdiff_t index)
11415ffd83dbSDimitry Andric ///     - Dereference an iterator pointing to the base object at the given
11425ffd83dbSDimitry Andric ///       index.
11435ffd83dbSDimitry Andric ///   * BaseT offset_base(const BaseT &base, ptrdiff_t index)
11445ffd83dbSDimitry Andric ///     - Return a new base that is offset from the provide base by 'index'
11455ffd83dbSDimitry Andric ///       elements.
11465ffd83dbSDimitry Andric template <typename DerivedT, typename BaseT, typename T,
11475ffd83dbSDimitry Andric           typename PointerT = T *, typename ReferenceT = T &>
11485ffd83dbSDimitry Andric class indexed_accessor_range_base {
11495ffd83dbSDimitry Andric public:
1150349cc55cSDimitry Andric   using RangeBaseT = indexed_accessor_range_base;
11515ffd83dbSDimitry Andric 
11525ffd83dbSDimitry Andric   /// An iterator element of this range.
11535ffd83dbSDimitry Andric   class iterator : public indexed_accessor_iterator<iterator, BaseT, T,
11545ffd83dbSDimitry Andric                                                     PointerT, ReferenceT> {
11555ffd83dbSDimitry Andric   public:
11565ffd83dbSDimitry Andric     // Index into this iterator, invoking a static method on the derived type.
11575ffd83dbSDimitry Andric     ReferenceT operator*() const {
11585ffd83dbSDimitry Andric       return DerivedT::dereference_iterator(this->getBase(), this->getIndex());
11595ffd83dbSDimitry Andric     }
11605ffd83dbSDimitry Andric 
11615ffd83dbSDimitry Andric   private:
11625ffd83dbSDimitry Andric     iterator(BaseT owner, ptrdiff_t curIndex)
1163349cc55cSDimitry Andric         : iterator::indexed_accessor_iterator(owner, curIndex) {}
11645ffd83dbSDimitry Andric 
11655ffd83dbSDimitry Andric     /// Allow access to the constructor.
11665ffd83dbSDimitry Andric     friend indexed_accessor_range_base<DerivedT, BaseT, T, PointerT,
11675ffd83dbSDimitry Andric                                        ReferenceT>;
11685ffd83dbSDimitry Andric   };
11695ffd83dbSDimitry Andric 
11705ffd83dbSDimitry Andric   indexed_accessor_range_base(iterator begin, iterator end)
11715ffd83dbSDimitry Andric       : base(offset_base(begin.getBase(), begin.getIndex())),
11725ffd83dbSDimitry Andric         count(end.getIndex() - begin.getIndex()) {}
11735ffd83dbSDimitry Andric   indexed_accessor_range_base(const iterator_range<iterator> &range)
11745ffd83dbSDimitry Andric       : indexed_accessor_range_base(range.begin(), range.end()) {}
11755ffd83dbSDimitry Andric   indexed_accessor_range_base(BaseT base, ptrdiff_t count)
11765ffd83dbSDimitry Andric       : base(base), count(count) {}
11775ffd83dbSDimitry Andric 
11785ffd83dbSDimitry Andric   iterator begin() const { return iterator(base, 0); }
11795ffd83dbSDimitry Andric   iterator end() const { return iterator(base, count); }
1180fe6060f1SDimitry Andric   ReferenceT operator[](size_t Index) const {
1181fe6060f1SDimitry Andric     assert(Index < size() && "invalid index for value range");
1182fe6060f1SDimitry Andric     return DerivedT::dereference_iterator(base, static_cast<ptrdiff_t>(Index));
11835ffd83dbSDimitry Andric   }
11845ffd83dbSDimitry Andric   ReferenceT front() const {
11855ffd83dbSDimitry Andric     assert(!empty() && "expected non-empty range");
11865ffd83dbSDimitry Andric     return (*this)[0];
11875ffd83dbSDimitry Andric   }
11885ffd83dbSDimitry Andric   ReferenceT back() const {
11895ffd83dbSDimitry Andric     assert(!empty() && "expected non-empty range");
11905ffd83dbSDimitry Andric     return (*this)[size() - 1];
11915ffd83dbSDimitry Andric   }
11925ffd83dbSDimitry Andric 
11935ffd83dbSDimitry Andric   /// Compare this range with another.
1194*81ad6265SDimitry Andric   template <typename OtherT>
1195*81ad6265SDimitry Andric   friend bool operator==(const indexed_accessor_range_base &lhs,
1196*81ad6265SDimitry Andric                          const OtherT &rhs) {
1197*81ad6265SDimitry Andric     return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
11985ffd83dbSDimitry Andric   }
1199*81ad6265SDimitry Andric   template <typename OtherT>
1200*81ad6265SDimitry Andric   friend bool operator!=(const indexed_accessor_range_base &lhs,
1201*81ad6265SDimitry Andric                          const OtherT &rhs) {
1202*81ad6265SDimitry Andric     return !(lhs == rhs);
12035ffd83dbSDimitry Andric   }
12045ffd83dbSDimitry Andric 
12055ffd83dbSDimitry Andric   /// Return the size of this range.
12065ffd83dbSDimitry Andric   size_t size() const { return count; }
12075ffd83dbSDimitry Andric 
12085ffd83dbSDimitry Andric   /// Return if the range is empty.
12095ffd83dbSDimitry Andric   bool empty() const { return size() == 0; }
12105ffd83dbSDimitry Andric 
12115ffd83dbSDimitry Andric   /// Drop the first N elements, and keep M elements.
12125ffd83dbSDimitry Andric   DerivedT slice(size_t n, size_t m) const {
12135ffd83dbSDimitry Andric     assert(n + m <= size() && "invalid size specifiers");
12145ffd83dbSDimitry Andric     return DerivedT(offset_base(base, n), m);
12155ffd83dbSDimitry Andric   }
12165ffd83dbSDimitry Andric 
12175ffd83dbSDimitry Andric   /// Drop the first n elements.
12185ffd83dbSDimitry Andric   DerivedT drop_front(size_t n = 1) const {
12195ffd83dbSDimitry Andric     assert(size() >= n && "Dropping more elements than exist");
12205ffd83dbSDimitry Andric     return slice(n, size() - n);
12215ffd83dbSDimitry Andric   }
12225ffd83dbSDimitry Andric   /// Drop the last n elements.
12235ffd83dbSDimitry Andric   DerivedT drop_back(size_t n = 1) const {
12245ffd83dbSDimitry Andric     assert(size() >= n && "Dropping more elements than exist");
12255ffd83dbSDimitry Andric     return DerivedT(base, size() - n);
12265ffd83dbSDimitry Andric   }
12275ffd83dbSDimitry Andric 
12285ffd83dbSDimitry Andric   /// Take the first n elements.
12295ffd83dbSDimitry Andric   DerivedT take_front(size_t n = 1) const {
12305ffd83dbSDimitry Andric     return n < size() ? drop_back(size() - n)
12315ffd83dbSDimitry Andric                       : static_cast<const DerivedT &>(*this);
12325ffd83dbSDimitry Andric   }
12335ffd83dbSDimitry Andric 
12345ffd83dbSDimitry Andric   /// Take the last n elements.
12355ffd83dbSDimitry Andric   DerivedT take_back(size_t n = 1) const {
12365ffd83dbSDimitry Andric     return n < size() ? drop_front(size() - n)
12375ffd83dbSDimitry Andric                       : static_cast<const DerivedT &>(*this);
12385ffd83dbSDimitry Andric   }
12395ffd83dbSDimitry Andric 
12405ffd83dbSDimitry Andric   /// Allow conversion to any type accepting an iterator_range.
12415ffd83dbSDimitry Andric   template <typename RangeT, typename = std::enable_if_t<std::is_constructible<
12425ffd83dbSDimitry Andric                                  RangeT, iterator_range<iterator>>::value>>
12435ffd83dbSDimitry Andric   operator RangeT() const {
12445ffd83dbSDimitry Andric     return RangeT(iterator_range<iterator>(*this));
12455ffd83dbSDimitry Andric   }
12465ffd83dbSDimitry Andric 
12475ffd83dbSDimitry Andric   /// Returns the base of this range.
12485ffd83dbSDimitry Andric   const BaseT &getBase() const { return base; }
12495ffd83dbSDimitry Andric 
12505ffd83dbSDimitry Andric private:
12515ffd83dbSDimitry Andric   /// Offset the given base by the given amount.
12525ffd83dbSDimitry Andric   static BaseT offset_base(const BaseT &base, size_t n) {
12535ffd83dbSDimitry Andric     return n == 0 ? base : DerivedT::offset_base(base, n);
12545ffd83dbSDimitry Andric   }
12555ffd83dbSDimitry Andric 
12565ffd83dbSDimitry Andric protected:
12575ffd83dbSDimitry Andric   indexed_accessor_range_base(const indexed_accessor_range_base &) = default;
12585ffd83dbSDimitry Andric   indexed_accessor_range_base(indexed_accessor_range_base &&) = default;
12595ffd83dbSDimitry Andric   indexed_accessor_range_base &
12605ffd83dbSDimitry Andric   operator=(const indexed_accessor_range_base &) = default;
12615ffd83dbSDimitry Andric 
12625ffd83dbSDimitry Andric   /// The base that owns the provided range of values.
12635ffd83dbSDimitry Andric   BaseT base;
12645ffd83dbSDimitry Andric   /// The size from the owning range.
12655ffd83dbSDimitry Andric   ptrdiff_t count;
12665ffd83dbSDimitry Andric };
12675ffd83dbSDimitry Andric } // end namespace detail
12685ffd83dbSDimitry Andric 
12695ffd83dbSDimitry Andric /// This class provides an implementation of a range of
12705ffd83dbSDimitry Andric /// indexed_accessor_iterators where the base is not indexable. Ranges with
12715ffd83dbSDimitry Andric /// bases that are offsetable should derive from indexed_accessor_range_base
12725ffd83dbSDimitry Andric /// instead. Derived range classes are expected to implement the following
12735ffd83dbSDimitry Andric /// static method:
12745ffd83dbSDimitry Andric ///   * ReferenceT dereference(const BaseT &base, ptrdiff_t index)
12755ffd83dbSDimitry Andric ///     - Dereference an iterator pointing to a parent base at the given index.
12765ffd83dbSDimitry Andric template <typename DerivedT, typename BaseT, typename T,
12775ffd83dbSDimitry Andric           typename PointerT = T *, typename ReferenceT = T &>
12785ffd83dbSDimitry Andric class indexed_accessor_range
12795ffd83dbSDimitry Andric     : public detail::indexed_accessor_range_base<
12805ffd83dbSDimitry Andric           DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT> {
12815ffd83dbSDimitry Andric public:
12825ffd83dbSDimitry Andric   indexed_accessor_range(BaseT base, ptrdiff_t startIndex, ptrdiff_t count)
12835ffd83dbSDimitry Andric       : detail::indexed_accessor_range_base<
12845ffd83dbSDimitry Andric             DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT>(
12855ffd83dbSDimitry Andric             std::make_pair(base, startIndex), count) {}
12865ffd83dbSDimitry Andric   using detail::indexed_accessor_range_base<
12875ffd83dbSDimitry Andric       DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT,
12885ffd83dbSDimitry Andric       ReferenceT>::indexed_accessor_range_base;
12895ffd83dbSDimitry Andric 
12905ffd83dbSDimitry Andric   /// Returns the current base of the range.
12915ffd83dbSDimitry Andric   const BaseT &getBase() const { return this->base.first; }
12925ffd83dbSDimitry Andric 
12935ffd83dbSDimitry Andric   /// Returns the current start index of the range.
12945ffd83dbSDimitry Andric   ptrdiff_t getStartIndex() const { return this->base.second; }
12955ffd83dbSDimitry Andric 
12965ffd83dbSDimitry Andric   /// See `detail::indexed_accessor_range_base` for details.
12975ffd83dbSDimitry Andric   static std::pair<BaseT, ptrdiff_t>
12985ffd83dbSDimitry Andric   offset_base(const std::pair<BaseT, ptrdiff_t> &base, ptrdiff_t index) {
12995ffd83dbSDimitry Andric     // We encode the internal base as a pair of the derived base and a start
13005ffd83dbSDimitry Andric     // index into the derived base.
13015ffd83dbSDimitry Andric     return std::make_pair(base.first, base.second + index);
13025ffd83dbSDimitry Andric   }
13035ffd83dbSDimitry Andric   /// See `detail::indexed_accessor_range_base` for details.
13045ffd83dbSDimitry Andric   static ReferenceT
13055ffd83dbSDimitry Andric   dereference_iterator(const std::pair<BaseT, ptrdiff_t> &base,
13065ffd83dbSDimitry Andric                        ptrdiff_t index) {
13075ffd83dbSDimitry Andric     return DerivedT::dereference(base.first, base.second + index);
13085ffd83dbSDimitry Andric   }
13095ffd83dbSDimitry Andric };
13105ffd83dbSDimitry Andric 
1311349cc55cSDimitry Andric namespace detail {
1312349cc55cSDimitry Andric /// Return a reference to the first or second member of a reference. Otherwise,
1313349cc55cSDimitry Andric /// return a copy of the member of a temporary.
1314349cc55cSDimitry Andric ///
1315349cc55cSDimitry Andric /// When passing a range whose iterators return values instead of references,
1316349cc55cSDimitry Andric /// the reference must be dropped from `decltype((elt.first))`, which will
1317349cc55cSDimitry Andric /// always be a reference, to avoid returning a reference to a temporary.
1318349cc55cSDimitry Andric template <typename EltTy, typename FirstTy> class first_or_second_type {
1319349cc55cSDimitry Andric public:
1320349cc55cSDimitry Andric   using type =
1321349cc55cSDimitry Andric       typename std::conditional_t<std::is_reference<EltTy>::value, FirstTy,
1322349cc55cSDimitry Andric                                   std::remove_reference_t<FirstTy>>;
1323349cc55cSDimitry Andric };
1324349cc55cSDimitry Andric } // end namespace detail
1325349cc55cSDimitry Andric 
1326e8d8bef9SDimitry Andric /// Given a container of pairs, return a range over the first elements.
1327e8d8bef9SDimitry Andric template <typename ContainerTy> auto make_first_range(ContainerTy &&c) {
1328349cc55cSDimitry Andric   using EltTy = decltype((*std::begin(c)));
1329349cc55cSDimitry Andric   return llvm::map_range(std::forward<ContainerTy>(c),
1330349cc55cSDimitry Andric                          [](EltTy elt) -> typename detail::first_or_second_type<
1331349cc55cSDimitry Andric                                            EltTy, decltype((elt.first))>::type {
1332e8d8bef9SDimitry Andric                            return elt.first;
1333e8d8bef9SDimitry Andric                          });
1334e8d8bef9SDimitry Andric }
1335e8d8bef9SDimitry Andric 
13365ffd83dbSDimitry Andric /// Given a container of pairs, return a range over the second elements.
13375ffd83dbSDimitry Andric template <typename ContainerTy> auto make_second_range(ContainerTy &&c) {
1338349cc55cSDimitry Andric   using EltTy = decltype((*std::begin(c)));
13395ffd83dbSDimitry Andric   return llvm::map_range(
13405ffd83dbSDimitry Andric       std::forward<ContainerTy>(c),
1341349cc55cSDimitry Andric       [](EltTy elt) ->
1342349cc55cSDimitry Andric       typename detail::first_or_second_type<EltTy,
1343349cc55cSDimitry Andric                                             decltype((elt.second))>::type {
13445ffd83dbSDimitry Andric         return elt.second;
13455ffd83dbSDimitry Andric       });
13465ffd83dbSDimitry Andric }
13475ffd83dbSDimitry Andric 
13480b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13490b57cec5SDimitry Andric //     Extra additions to <utility>
13500b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13510b57cec5SDimitry Andric 
13520b57cec5SDimitry Andric /// Function object to check whether the first component of a std::pair
13530b57cec5SDimitry Andric /// compares less than the first component of another std::pair.
13540b57cec5SDimitry Andric struct less_first {
13550b57cec5SDimitry Andric   template <typename T> bool operator()(const T &lhs, const T &rhs) const {
1356349cc55cSDimitry Andric     return std::less<>()(lhs.first, rhs.first);
13570b57cec5SDimitry Andric   }
13580b57cec5SDimitry Andric };
13590b57cec5SDimitry Andric 
13600b57cec5SDimitry Andric /// Function object to check whether the second component of a std::pair
13610b57cec5SDimitry Andric /// compares less than the second component of another std::pair.
13620b57cec5SDimitry Andric struct less_second {
13630b57cec5SDimitry Andric   template <typename T> bool operator()(const T &lhs, const T &rhs) const {
1364349cc55cSDimitry Andric     return std::less<>()(lhs.second, rhs.second);
13650b57cec5SDimitry Andric   }
13660b57cec5SDimitry Andric };
13670b57cec5SDimitry Andric 
13680b57cec5SDimitry Andric /// \brief Function object to apply a binary function to the first component of
13690b57cec5SDimitry Andric /// a std::pair.
13700b57cec5SDimitry Andric template<typename FuncTy>
13710b57cec5SDimitry Andric struct on_first {
13720b57cec5SDimitry Andric   FuncTy func;
13730b57cec5SDimitry Andric 
13740b57cec5SDimitry Andric   template <typename T>
13755ffd83dbSDimitry Andric   decltype(auto) operator()(const T &lhs, const T &rhs) const {
13760b57cec5SDimitry Andric     return func(lhs.first, rhs.first);
13770b57cec5SDimitry Andric   }
13780b57cec5SDimitry Andric };
13790b57cec5SDimitry Andric 
13800b57cec5SDimitry Andric /// Utility type to build an inheritance chain that makes it easy to rank
13810b57cec5SDimitry Andric /// overload candidates.
13820b57cec5SDimitry Andric template <int N> struct rank : rank<N - 1> {};
13830b57cec5SDimitry Andric template <> struct rank<0> {};
13840b57cec5SDimitry Andric 
13850b57cec5SDimitry Andric /// traits class for checking whether type T is one of any of the given
13860b57cec5SDimitry Andric /// types in the variadic list.
1387fe6060f1SDimitry Andric template <typename T, typename... Ts>
1388fe6060f1SDimitry Andric using is_one_of = disjunction<std::is_same<T, Ts>...>;
13890b57cec5SDimitry Andric 
13900b57cec5SDimitry Andric /// traits class for checking whether type T is a base class for all
13910b57cec5SDimitry Andric ///  the given types in the variadic list.
1392fe6060f1SDimitry Andric template <typename T, typename... Ts>
1393fe6060f1SDimitry Andric using are_base_of = conjunction<std::is_base_of<T, Ts>...>;
1394fe6060f1SDimitry Andric 
1395fe6060f1SDimitry Andric namespace detail {
1396fe6060f1SDimitry Andric template <typename... Ts> struct Visitor;
1397fe6060f1SDimitry Andric 
1398fe6060f1SDimitry Andric template <typename HeadT, typename... TailTs>
1399fe6060f1SDimitry Andric struct Visitor<HeadT, TailTs...> : remove_cvref_t<HeadT>, Visitor<TailTs...> {
1400fe6060f1SDimitry Andric   explicit constexpr Visitor(HeadT &&Head, TailTs &&...Tail)
1401fe6060f1SDimitry Andric       : remove_cvref_t<HeadT>(std::forward<HeadT>(Head)),
1402fe6060f1SDimitry Andric         Visitor<TailTs...>(std::forward<TailTs>(Tail)...) {}
1403fe6060f1SDimitry Andric   using remove_cvref_t<HeadT>::operator();
1404fe6060f1SDimitry Andric   using Visitor<TailTs...>::operator();
14050b57cec5SDimitry Andric };
14060b57cec5SDimitry Andric 
1407fe6060f1SDimitry Andric template <typename HeadT> struct Visitor<HeadT> : remove_cvref_t<HeadT> {
1408fe6060f1SDimitry Andric   explicit constexpr Visitor(HeadT &&Head)
1409fe6060f1SDimitry Andric       : remove_cvref_t<HeadT>(std::forward<HeadT>(Head)) {}
1410fe6060f1SDimitry Andric   using remove_cvref_t<HeadT>::operator();
14110b57cec5SDimitry Andric };
1412fe6060f1SDimitry Andric } // namespace detail
1413fe6060f1SDimitry Andric 
1414fe6060f1SDimitry Andric /// Returns an opaquely-typed Callable object whose operator() overload set is
1415fe6060f1SDimitry Andric /// the sum of the operator() overload sets of each CallableT in CallableTs.
1416fe6060f1SDimitry Andric ///
1417fe6060f1SDimitry Andric /// The type of the returned object derives from each CallableT in CallableTs.
1418fe6060f1SDimitry Andric /// The returned object is constructed by invoking the appropriate copy or move
1419fe6060f1SDimitry Andric /// constructor of each CallableT, as selected by overload resolution on the
1420fe6060f1SDimitry Andric /// corresponding argument to makeVisitor.
1421fe6060f1SDimitry Andric ///
1422fe6060f1SDimitry Andric /// Example:
1423fe6060f1SDimitry Andric ///
1424fe6060f1SDimitry Andric /// \code
1425fe6060f1SDimitry Andric /// auto visitor = makeVisitor([](auto) { return "unhandled type"; },
1426fe6060f1SDimitry Andric ///                            [](int i) { return "int"; },
1427fe6060f1SDimitry Andric ///                            [](std::string s) { return "str"; });
1428fe6060f1SDimitry Andric /// auto a = visitor(42);    // `a` is now "int".
1429fe6060f1SDimitry Andric /// auto b = visitor("foo"); // `b` is now "str".
1430fe6060f1SDimitry Andric /// auto c = visitor(3.14f); // `c` is now "unhandled type".
1431fe6060f1SDimitry Andric /// \endcode
1432fe6060f1SDimitry Andric ///
1433fe6060f1SDimitry Andric /// Example of making a visitor with a lambda which captures a move-only type:
1434fe6060f1SDimitry Andric ///
1435fe6060f1SDimitry Andric /// \code
1436fe6060f1SDimitry Andric /// std::unique_ptr<FooHandler> FH = /* ... */;
1437fe6060f1SDimitry Andric /// auto visitor = makeVisitor(
1438fe6060f1SDimitry Andric ///     [FH{std::move(FH)}](Foo F) { return FH->handle(F); },
1439fe6060f1SDimitry Andric ///     [](int i) { return i; },
1440fe6060f1SDimitry Andric ///     [](std::string s) { return atoi(s); });
1441fe6060f1SDimitry Andric /// \endcode
1442fe6060f1SDimitry Andric template <typename... CallableTs>
1443fe6060f1SDimitry Andric constexpr decltype(auto) makeVisitor(CallableTs &&...Callables) {
1444fe6060f1SDimitry Andric   return detail::Visitor<CallableTs...>(std::forward<CallableTs>(Callables)...);
1445fe6060f1SDimitry Andric }
14460b57cec5SDimitry Andric 
14470b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14481fd87a68SDimitry Andric //     Extra additions to <algorithm>
14490b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
14500b57cec5SDimitry Andric 
14515ffd83dbSDimitry Andric // We have a copy here so that LLVM behaves the same when using different
14525ffd83dbSDimitry Andric // standard libraries.
14535ffd83dbSDimitry Andric template <class Iterator, class RNG>
14545ffd83dbSDimitry Andric void shuffle(Iterator first, Iterator last, RNG &&g) {
14555ffd83dbSDimitry Andric   // It would be better to use a std::uniform_int_distribution,
14565ffd83dbSDimitry Andric   // but that would be stdlib dependent.
1457fe6060f1SDimitry Andric   typedef
1458fe6060f1SDimitry Andric       typename std::iterator_traits<Iterator>::difference_type difference_type;
1459fe6060f1SDimitry Andric   for (auto size = last - first; size > 1; ++first, (void)--size) {
1460fe6060f1SDimitry Andric     difference_type offset = g() % size;
1461fe6060f1SDimitry Andric     // Avoid self-assignment due to incorrect assertions in libstdc++
1462fe6060f1SDimitry Andric     // containers (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85828).
1463fe6060f1SDimitry Andric     if (offset != difference_type(0))
1464fe6060f1SDimitry Andric       std::iter_swap(first, first + offset);
1465fe6060f1SDimitry Andric   }
14665ffd83dbSDimitry Andric }
14675ffd83dbSDimitry Andric 
14680b57cec5SDimitry Andric /// Adapt std::less<T> for array_pod_sort.
14690b57cec5SDimitry Andric template<typename T>
14700b57cec5SDimitry Andric inline int array_pod_sort_comparator(const void *P1, const void *P2) {
14710b57cec5SDimitry Andric   if (std::less<T>()(*reinterpret_cast<const T*>(P1),
14720b57cec5SDimitry Andric                      *reinterpret_cast<const T*>(P2)))
14730b57cec5SDimitry Andric     return -1;
14740b57cec5SDimitry Andric   if (std::less<T>()(*reinterpret_cast<const T*>(P2),
14750b57cec5SDimitry Andric                      *reinterpret_cast<const T*>(P1)))
14760b57cec5SDimitry Andric     return 1;
14770b57cec5SDimitry Andric   return 0;
14780b57cec5SDimitry Andric }
14790b57cec5SDimitry Andric 
14800b57cec5SDimitry Andric /// get_array_pod_sort_comparator - This is an internal helper function used to
14810b57cec5SDimitry Andric /// get type deduction of T right.
14820b57cec5SDimitry Andric template<typename T>
14830b57cec5SDimitry Andric inline int (*get_array_pod_sort_comparator(const T &))
14840b57cec5SDimitry Andric              (const void*, const void*) {
14850b57cec5SDimitry Andric   return array_pod_sort_comparator<T>;
14860b57cec5SDimitry Andric }
14870b57cec5SDimitry Andric 
1488480093f4SDimitry Andric #ifdef EXPENSIVE_CHECKS
1489480093f4SDimitry Andric namespace detail {
1490480093f4SDimitry Andric 
1491480093f4SDimitry Andric inline unsigned presortShuffleEntropy() {
1492480093f4SDimitry Andric   static unsigned Result(std::random_device{}());
1493480093f4SDimitry Andric   return Result;
1494480093f4SDimitry Andric }
1495480093f4SDimitry Andric 
1496480093f4SDimitry Andric template <class IteratorTy>
1497480093f4SDimitry Andric inline void presortShuffle(IteratorTy Start, IteratorTy End) {
1498480093f4SDimitry Andric   std::mt19937 Generator(presortShuffleEntropy());
1499fe6060f1SDimitry Andric   llvm::shuffle(Start, End, Generator);
1500480093f4SDimitry Andric }
1501480093f4SDimitry Andric 
1502480093f4SDimitry Andric } // end namespace detail
1503480093f4SDimitry Andric #endif
1504480093f4SDimitry Andric 
15050b57cec5SDimitry Andric /// array_pod_sort - This sorts an array with the specified start and end
15060b57cec5SDimitry Andric /// extent.  This is just like std::sort, except that it calls qsort instead of
15070b57cec5SDimitry Andric /// using an inlined template.  qsort is slightly slower than std::sort, but
15080b57cec5SDimitry Andric /// most sorts are not performance critical in LLVM and std::sort has to be
15090b57cec5SDimitry Andric /// template instantiated for each type, leading to significant measured code
15100b57cec5SDimitry Andric /// bloat.  This function should generally be used instead of std::sort where
15110b57cec5SDimitry Andric /// possible.
15120b57cec5SDimitry Andric ///
15130b57cec5SDimitry Andric /// This function assumes that you have simple POD-like types that can be
15140b57cec5SDimitry Andric /// compared with std::less and can be moved with memcpy.  If this isn't true,
15150b57cec5SDimitry Andric /// you should use std::sort.
15160b57cec5SDimitry Andric ///
15170b57cec5SDimitry Andric /// NOTE: If qsort_r were portable, we could allow a custom comparator and
15180b57cec5SDimitry Andric /// default to std::less.
15190b57cec5SDimitry Andric template<class IteratorTy>
15200b57cec5SDimitry Andric inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
15210b57cec5SDimitry Andric   // Don't inefficiently call qsort with one element or trigger undefined
15220b57cec5SDimitry Andric   // behavior with an empty sequence.
15230b57cec5SDimitry Andric   auto NElts = End - Start;
15240b57cec5SDimitry Andric   if (NElts <= 1) return;
15250b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
1526480093f4SDimitry Andric   detail::presortShuffle<IteratorTy>(Start, End);
15270b57cec5SDimitry Andric #endif
15280b57cec5SDimitry Andric   qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
15290b57cec5SDimitry Andric }
15300b57cec5SDimitry Andric 
15310b57cec5SDimitry Andric template <class IteratorTy>
15320b57cec5SDimitry Andric inline void array_pod_sort(
15330b57cec5SDimitry Andric     IteratorTy Start, IteratorTy End,
15340b57cec5SDimitry Andric     int (*Compare)(
15350b57cec5SDimitry Andric         const typename std::iterator_traits<IteratorTy>::value_type *,
15360b57cec5SDimitry Andric         const typename std::iterator_traits<IteratorTy>::value_type *)) {
15370b57cec5SDimitry Andric   // Don't inefficiently call qsort with one element or trigger undefined
15380b57cec5SDimitry Andric   // behavior with an empty sequence.
15390b57cec5SDimitry Andric   auto NElts = End - Start;
15400b57cec5SDimitry Andric   if (NElts <= 1) return;
15410b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
1542480093f4SDimitry Andric   detail::presortShuffle<IteratorTy>(Start, End);
15430b57cec5SDimitry Andric #endif
15440b57cec5SDimitry Andric   qsort(&*Start, NElts, sizeof(*Start),
15450b57cec5SDimitry Andric         reinterpret_cast<int (*)(const void *, const void *)>(Compare));
15460b57cec5SDimitry Andric }
15470b57cec5SDimitry Andric 
15485ffd83dbSDimitry Andric namespace detail {
15495ffd83dbSDimitry Andric template <typename T>
15505ffd83dbSDimitry Andric // We can use qsort if the iterator type is a pointer and the underlying value
15515ffd83dbSDimitry Andric // is trivially copyable.
15525ffd83dbSDimitry Andric using sort_trivially_copyable = conjunction<
15535ffd83dbSDimitry Andric     std::is_pointer<T>,
1554e8d8bef9SDimitry Andric     std::is_trivially_copyable<typename std::iterator_traits<T>::value_type>>;
15555ffd83dbSDimitry Andric } // namespace detail
15565ffd83dbSDimitry Andric 
15570b57cec5SDimitry Andric // Provide wrappers to std::sort which shuffle the elements before sorting
15580b57cec5SDimitry Andric // to help uncover non-deterministic behavior (PR35135).
15595ffd83dbSDimitry Andric template <typename IteratorTy,
15605ffd83dbSDimitry Andric           std::enable_if_t<!detail::sort_trivially_copyable<IteratorTy>::value,
15615ffd83dbSDimitry Andric                            int> = 0>
15620b57cec5SDimitry Andric inline void sort(IteratorTy Start, IteratorTy End) {
15630b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
1564480093f4SDimitry Andric   detail::presortShuffle<IteratorTy>(Start, End);
15650b57cec5SDimitry Andric #endif
15660b57cec5SDimitry Andric   std::sort(Start, End);
15670b57cec5SDimitry Andric }
15680b57cec5SDimitry Andric 
15695ffd83dbSDimitry Andric // Forward trivially copyable types to array_pod_sort. This avoids a large
15705ffd83dbSDimitry Andric // amount of code bloat for a minor performance hit.
15715ffd83dbSDimitry Andric template <typename IteratorTy,
15725ffd83dbSDimitry Andric           std::enable_if_t<detail::sort_trivially_copyable<IteratorTy>::value,
15735ffd83dbSDimitry Andric                            int> = 0>
15745ffd83dbSDimitry Andric inline void sort(IteratorTy Start, IteratorTy End) {
15755ffd83dbSDimitry Andric   array_pod_sort(Start, End);
15765ffd83dbSDimitry Andric }
15775ffd83dbSDimitry Andric 
15780b57cec5SDimitry Andric template <typename Container> inline void sort(Container &&C) {
15790b57cec5SDimitry Andric   llvm::sort(adl_begin(C), adl_end(C));
15800b57cec5SDimitry Andric }
15810b57cec5SDimitry Andric 
15820b57cec5SDimitry Andric template <typename IteratorTy, typename Compare>
15830b57cec5SDimitry Andric inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
15840b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
1585480093f4SDimitry Andric   detail::presortShuffle<IteratorTy>(Start, End);
15860b57cec5SDimitry Andric #endif
15870b57cec5SDimitry Andric   std::sort(Start, End, Comp);
15880b57cec5SDimitry Andric }
15890b57cec5SDimitry Andric 
15900b57cec5SDimitry Andric template <typename Container, typename Compare>
15910b57cec5SDimitry Andric inline void sort(Container &&C, Compare Comp) {
15920b57cec5SDimitry Andric   llvm::sort(adl_begin(C), adl_end(C), Comp);
15930b57cec5SDimitry Andric }
15940b57cec5SDimitry Andric 
15950b57cec5SDimitry Andric /// Get the size of a range. This is a wrapper function around std::distance
15960b57cec5SDimitry Andric /// which is only enabled when the operation is O(1).
15970b57cec5SDimitry Andric template <typename R>
15985ffd83dbSDimitry Andric auto size(R &&Range,
1599e8d8bef9SDimitry Andric           std::enable_if_t<
1600e8d8bef9SDimitry Andric               std::is_base_of<std::random_access_iterator_tag,
1601e8d8bef9SDimitry Andric                               typename std::iterator_traits<decltype(
1602e8d8bef9SDimitry Andric                                   Range.begin())>::iterator_category>::value,
16035ffd83dbSDimitry Andric               void> * = nullptr) {
16040b57cec5SDimitry Andric   return std::distance(Range.begin(), Range.end());
16050b57cec5SDimitry Andric }
16060b57cec5SDimitry Andric 
16070b57cec5SDimitry Andric /// Provide wrappers to std::for_each which take ranges instead of having to
16080b57cec5SDimitry Andric /// pass begin/end explicitly.
1609e8d8bef9SDimitry Andric template <typename R, typename UnaryFunction>
1610e8d8bef9SDimitry Andric UnaryFunction for_each(R &&Range, UnaryFunction F) {
1611e8d8bef9SDimitry Andric   return std::for_each(adl_begin(Range), adl_end(Range), F);
16120b57cec5SDimitry Andric }
16130b57cec5SDimitry Andric 
16140b57cec5SDimitry Andric /// Provide wrappers to std::all_of which take ranges instead of having to pass
16150b57cec5SDimitry Andric /// begin/end explicitly.
16160b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
16170b57cec5SDimitry Andric bool all_of(R &&Range, UnaryPredicate P) {
16180b57cec5SDimitry Andric   return std::all_of(adl_begin(Range), adl_end(Range), P);
16190b57cec5SDimitry Andric }
16200b57cec5SDimitry Andric 
16210b57cec5SDimitry Andric /// Provide wrappers to std::any_of which take ranges instead of having to pass
16220b57cec5SDimitry Andric /// begin/end explicitly.
16230b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
16240b57cec5SDimitry Andric bool any_of(R &&Range, UnaryPredicate P) {
16250b57cec5SDimitry Andric   return std::any_of(adl_begin(Range), adl_end(Range), P);
16260b57cec5SDimitry Andric }
16270b57cec5SDimitry Andric 
16280b57cec5SDimitry Andric /// Provide wrappers to std::none_of which take ranges instead of having to pass
16290b57cec5SDimitry Andric /// begin/end explicitly.
16300b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
16310b57cec5SDimitry Andric bool none_of(R &&Range, UnaryPredicate P) {
16320b57cec5SDimitry Andric   return std::none_of(adl_begin(Range), adl_end(Range), P);
16330b57cec5SDimitry Andric }
16340b57cec5SDimitry Andric 
16350b57cec5SDimitry Andric /// Provide wrappers to std::find which take ranges instead of having to pass
16360b57cec5SDimitry Andric /// begin/end explicitly.
16375ffd83dbSDimitry Andric template <typename R, typename T> auto find(R &&Range, const T &Val) {
16380b57cec5SDimitry Andric   return std::find(adl_begin(Range), adl_end(Range), Val);
16390b57cec5SDimitry Andric }
16400b57cec5SDimitry Andric 
16410b57cec5SDimitry Andric /// Provide wrappers to std::find_if which take ranges instead of having to pass
16420b57cec5SDimitry Andric /// begin/end explicitly.
16430b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
16445ffd83dbSDimitry Andric auto find_if(R &&Range, UnaryPredicate P) {
16450b57cec5SDimitry Andric   return std::find_if(adl_begin(Range), adl_end(Range), P);
16460b57cec5SDimitry Andric }
16470b57cec5SDimitry Andric 
16480b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
16495ffd83dbSDimitry Andric auto find_if_not(R &&Range, UnaryPredicate P) {
16500b57cec5SDimitry Andric   return std::find_if_not(adl_begin(Range), adl_end(Range), P);
16510b57cec5SDimitry Andric }
16520b57cec5SDimitry Andric 
16530b57cec5SDimitry Andric /// Provide wrappers to std::remove_if which take ranges instead of having to
16540b57cec5SDimitry Andric /// pass begin/end explicitly.
16550b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
16565ffd83dbSDimitry Andric auto remove_if(R &&Range, UnaryPredicate P) {
16570b57cec5SDimitry Andric   return std::remove_if(adl_begin(Range), adl_end(Range), P);
16580b57cec5SDimitry Andric }
16590b57cec5SDimitry Andric 
16600b57cec5SDimitry Andric /// Provide wrappers to std::copy_if which take ranges instead of having to
16610b57cec5SDimitry Andric /// pass begin/end explicitly.
16620b57cec5SDimitry Andric template <typename R, typename OutputIt, typename UnaryPredicate>
16630b57cec5SDimitry Andric OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) {
16640b57cec5SDimitry Andric   return std::copy_if(adl_begin(Range), adl_end(Range), Out, P);
16650b57cec5SDimitry Andric }
16660b57cec5SDimitry Andric 
16670b57cec5SDimitry Andric template <typename R, typename OutputIt>
16680b57cec5SDimitry Andric OutputIt copy(R &&Range, OutputIt Out) {
16690b57cec5SDimitry Andric   return std::copy(adl_begin(Range), adl_end(Range), Out);
16700b57cec5SDimitry Andric }
16710b57cec5SDimitry Andric 
1672e8d8bef9SDimitry Andric /// Provide wrappers to std::move which take ranges instead of having to
1673e8d8bef9SDimitry Andric /// pass begin/end explicitly.
1674e8d8bef9SDimitry Andric template <typename R, typename OutputIt>
1675e8d8bef9SDimitry Andric OutputIt move(R &&Range, OutputIt Out) {
1676e8d8bef9SDimitry Andric   return std::move(adl_begin(Range), adl_end(Range), Out);
1677e8d8bef9SDimitry Andric }
1678e8d8bef9SDimitry Andric 
16790b57cec5SDimitry Andric /// Wrapper function around std::find to detect if an element exists
16800b57cec5SDimitry Andric /// in a container.
16810b57cec5SDimitry Andric template <typename R, typename E>
16820b57cec5SDimitry Andric bool is_contained(R &&Range, const E &Element) {
16830b57cec5SDimitry Andric   return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range);
16840b57cec5SDimitry Andric }
16850b57cec5SDimitry Andric 
1686*81ad6265SDimitry Andric template <typename T>
1687*81ad6265SDimitry Andric constexpr bool is_contained(std::initializer_list<T> Set, T Value) {
1688*81ad6265SDimitry Andric   // TODO: Use std::find when we switch to C++20.
1689*81ad6265SDimitry Andric   for (T V : Set)
1690*81ad6265SDimitry Andric     if (V == Value)
1691*81ad6265SDimitry Andric       return true;
1692*81ad6265SDimitry Andric   return false;
1693*81ad6265SDimitry Andric }
1694*81ad6265SDimitry Andric 
16955ffd83dbSDimitry Andric /// Wrapper function around std::is_sorted to check if elements in a range \p R
16965ffd83dbSDimitry Andric /// are sorted with respect to a comparator \p C.
16975ffd83dbSDimitry Andric template <typename R, typename Compare> bool is_sorted(R &&Range, Compare C) {
16985ffd83dbSDimitry Andric   return std::is_sorted(adl_begin(Range), adl_end(Range), C);
16995ffd83dbSDimitry Andric }
17005ffd83dbSDimitry Andric 
17015ffd83dbSDimitry Andric /// Wrapper function around std::is_sorted to check if elements in a range \p R
17025ffd83dbSDimitry Andric /// are sorted in non-descending order.
17035ffd83dbSDimitry Andric template <typename R> bool is_sorted(R &&Range) {
17045ffd83dbSDimitry Andric   return std::is_sorted(adl_begin(Range), adl_end(Range));
17055ffd83dbSDimitry Andric }
17065ffd83dbSDimitry Andric 
17070b57cec5SDimitry Andric /// Wrapper function around std::count to count the number of times an element
17080b57cec5SDimitry Andric /// \p Element occurs in the given range \p Range.
17095ffd83dbSDimitry Andric template <typename R, typename E> auto count(R &&Range, const E &Element) {
17100b57cec5SDimitry Andric   return std::count(adl_begin(Range), adl_end(Range), Element);
17110b57cec5SDimitry Andric }
17120b57cec5SDimitry Andric 
17130b57cec5SDimitry Andric /// Wrapper function around std::count_if to count the number of times an
17140b57cec5SDimitry Andric /// element satisfying a given predicate occurs in a range.
17150b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
17165ffd83dbSDimitry Andric auto count_if(R &&Range, UnaryPredicate P) {
17170b57cec5SDimitry Andric   return std::count_if(adl_begin(Range), adl_end(Range), P);
17180b57cec5SDimitry Andric }
17190b57cec5SDimitry Andric 
17200b57cec5SDimitry Andric /// Wrapper function around std::transform to apply a function to a range and
17210b57cec5SDimitry Andric /// store the result elsewhere.
1722e8d8bef9SDimitry Andric template <typename R, typename OutputIt, typename UnaryFunction>
1723e8d8bef9SDimitry Andric OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F) {
1724e8d8bef9SDimitry Andric   return std::transform(adl_begin(Range), adl_end(Range), d_first, F);
17250b57cec5SDimitry Andric }
17260b57cec5SDimitry Andric 
17270b57cec5SDimitry Andric /// Provide wrappers to std::partition which take ranges instead of having to
17280b57cec5SDimitry Andric /// pass begin/end explicitly.
17290b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
17305ffd83dbSDimitry Andric auto partition(R &&Range, UnaryPredicate P) {
17310b57cec5SDimitry Andric   return std::partition(adl_begin(Range), adl_end(Range), P);
17320b57cec5SDimitry Andric }
17330b57cec5SDimitry Andric 
17340b57cec5SDimitry Andric /// Provide wrappers to std::lower_bound which take ranges instead of having to
17350b57cec5SDimitry Andric /// pass begin/end explicitly.
17365ffd83dbSDimitry Andric template <typename R, typename T> auto lower_bound(R &&Range, T &&Value) {
17370b57cec5SDimitry Andric   return std::lower_bound(adl_begin(Range), adl_end(Range),
17380b57cec5SDimitry Andric                           std::forward<T>(Value));
17390b57cec5SDimitry Andric }
17400b57cec5SDimitry Andric 
17410b57cec5SDimitry Andric template <typename R, typename T, typename Compare>
17425ffd83dbSDimitry Andric auto lower_bound(R &&Range, T &&Value, Compare C) {
17430b57cec5SDimitry Andric   return std::lower_bound(adl_begin(Range), adl_end(Range),
17440b57cec5SDimitry Andric                           std::forward<T>(Value), C);
17450b57cec5SDimitry Andric }
17460b57cec5SDimitry Andric 
17470b57cec5SDimitry Andric /// Provide wrappers to std::upper_bound which take ranges instead of having to
17480b57cec5SDimitry Andric /// pass begin/end explicitly.
17495ffd83dbSDimitry Andric template <typename R, typename T> auto upper_bound(R &&Range, T &&Value) {
17500b57cec5SDimitry Andric   return std::upper_bound(adl_begin(Range), adl_end(Range),
17510b57cec5SDimitry Andric                           std::forward<T>(Value));
17520b57cec5SDimitry Andric }
17530b57cec5SDimitry Andric 
17540b57cec5SDimitry Andric template <typename R, typename T, typename Compare>
17555ffd83dbSDimitry Andric auto upper_bound(R &&Range, T &&Value, Compare C) {
17560b57cec5SDimitry Andric   return std::upper_bound(adl_begin(Range), adl_end(Range),
17570b57cec5SDimitry Andric                           std::forward<T>(Value), C);
17580b57cec5SDimitry Andric }
17590b57cec5SDimitry Andric 
17600b57cec5SDimitry Andric template <typename R>
17610b57cec5SDimitry Andric void stable_sort(R &&Range) {
17620b57cec5SDimitry Andric   std::stable_sort(adl_begin(Range), adl_end(Range));
17630b57cec5SDimitry Andric }
17640b57cec5SDimitry Andric 
17650b57cec5SDimitry Andric template <typename R, typename Compare>
17660b57cec5SDimitry Andric void stable_sort(R &&Range, Compare C) {
17670b57cec5SDimitry Andric   std::stable_sort(adl_begin(Range), adl_end(Range), C);
17680b57cec5SDimitry Andric }
17690b57cec5SDimitry Andric 
17700b57cec5SDimitry Andric /// Binary search for the first iterator in a range where a predicate is false.
17710b57cec5SDimitry Andric /// Requires that C is always true below some limit, and always false above it.
17720b57cec5SDimitry Andric template <typename R, typename Predicate,
17730b57cec5SDimitry Andric           typename Val = decltype(*adl_begin(std::declval<R>()))>
17745ffd83dbSDimitry Andric auto partition_point(R &&Range, Predicate P) {
17750b57cec5SDimitry Andric   return std::partition_point(adl_begin(Range), adl_end(Range), P);
17760b57cec5SDimitry Andric }
17770b57cec5SDimitry Andric 
1778fe6060f1SDimitry Andric template<typename Range, typename Predicate>
1779fe6060f1SDimitry Andric auto unique(Range &&R, Predicate P) {
1780fe6060f1SDimitry Andric   return std::unique(adl_begin(R), adl_end(R), P);
1781fe6060f1SDimitry Andric }
1782fe6060f1SDimitry Andric 
1783fe6060f1SDimitry Andric /// Wrapper function around std::equal to detect if pair-wise elements between
1784fe6060f1SDimitry Andric /// two ranges are the same.
1785fe6060f1SDimitry Andric template <typename L, typename R> bool equal(L &&LRange, R &&RRange) {
1786fe6060f1SDimitry Andric   return std::equal(adl_begin(LRange), adl_end(LRange), adl_begin(RRange),
1787fe6060f1SDimitry Andric                     adl_end(RRange));
1788fe6060f1SDimitry Andric }
1789fe6060f1SDimitry Andric 
17900b57cec5SDimitry Andric /// Wrapper function around std::equal to detect if all elements
17910b57cec5SDimitry Andric /// in a container are same.
17920b57cec5SDimitry Andric template <typename R>
17930b57cec5SDimitry Andric bool is_splat(R &&Range) {
17940b57cec5SDimitry Andric   size_t range_size = size(Range);
17950b57cec5SDimitry Andric   return range_size != 0 && (range_size == 1 ||
17960b57cec5SDimitry Andric          std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range)));
17970b57cec5SDimitry Andric }
17980b57cec5SDimitry Andric 
17990b57cec5SDimitry Andric /// Provide a container algorithm similar to C++ Library Fundamentals v2's
18000b57cec5SDimitry Andric /// `erase_if` which is equivalent to:
18010b57cec5SDimitry Andric ///
18020b57cec5SDimitry Andric ///   C.erase(remove_if(C, pred), C.end());
18030b57cec5SDimitry Andric ///
18040b57cec5SDimitry Andric /// This version works for any container with an erase method call accepting
18050b57cec5SDimitry Andric /// two iterators.
18060b57cec5SDimitry Andric template <typename Container, typename UnaryPredicate>
18070b57cec5SDimitry Andric void erase_if(Container &C, UnaryPredicate P) {
18080b57cec5SDimitry Andric   C.erase(remove_if(C, P), C.end());
18090b57cec5SDimitry Andric }
18100b57cec5SDimitry Andric 
1811e8d8bef9SDimitry Andric /// Wrapper function to remove a value from a container:
1812e8d8bef9SDimitry Andric ///
1813e8d8bef9SDimitry Andric /// C.erase(remove(C.begin(), C.end(), V), C.end());
1814e8d8bef9SDimitry Andric template <typename Container, typename ValueType>
1815e8d8bef9SDimitry Andric void erase_value(Container &C, ValueType V) {
1816e8d8bef9SDimitry Andric   C.erase(std::remove(C.begin(), C.end(), V), C.end());
1817e8d8bef9SDimitry Andric }
1818e8d8bef9SDimitry Andric 
1819e8d8bef9SDimitry Andric /// Wrapper function to append a range to a container.
1820e8d8bef9SDimitry Andric ///
1821e8d8bef9SDimitry Andric /// C.insert(C.end(), R.begin(), R.end());
1822e8d8bef9SDimitry Andric template <typename Container, typename Range>
1823e8d8bef9SDimitry Andric inline void append_range(Container &C, Range &&R) {
1824e8d8bef9SDimitry Andric   C.insert(C.end(), R.begin(), R.end());
1825e8d8bef9SDimitry Andric }
1826e8d8bef9SDimitry Andric 
18270b57cec5SDimitry Andric /// Given a sequence container Cont, replace the range [ContIt, ContEnd) with
18280b57cec5SDimitry Andric /// the range [ValIt, ValEnd) (which is not from the same container).
18290b57cec5SDimitry Andric template<typename Container, typename RandomAccessIterator>
18300b57cec5SDimitry Andric void replace(Container &Cont, typename Container::iterator ContIt,
18310b57cec5SDimitry Andric              typename Container::iterator ContEnd, RandomAccessIterator ValIt,
18320b57cec5SDimitry Andric              RandomAccessIterator ValEnd) {
18330b57cec5SDimitry Andric   while (true) {
18340b57cec5SDimitry Andric     if (ValIt == ValEnd) {
18350b57cec5SDimitry Andric       Cont.erase(ContIt, ContEnd);
18360b57cec5SDimitry Andric       return;
18370b57cec5SDimitry Andric     } else if (ContIt == ContEnd) {
18380b57cec5SDimitry Andric       Cont.insert(ContIt, ValIt, ValEnd);
18390b57cec5SDimitry Andric       return;
18400b57cec5SDimitry Andric     }
18410b57cec5SDimitry Andric     *ContIt++ = *ValIt++;
18420b57cec5SDimitry Andric   }
18430b57cec5SDimitry Andric }
18440b57cec5SDimitry Andric 
18450b57cec5SDimitry Andric /// Given a sequence container Cont, replace the range [ContIt, ContEnd) with
18460b57cec5SDimitry Andric /// the range R.
18470b57cec5SDimitry Andric template<typename Container, typename Range = std::initializer_list<
18480b57cec5SDimitry Andric                                  typename Container::value_type>>
18490b57cec5SDimitry Andric void replace(Container &Cont, typename Container::iterator ContIt,
18500b57cec5SDimitry Andric              typename Container::iterator ContEnd, Range R) {
18510b57cec5SDimitry Andric   replace(Cont, ContIt, ContEnd, R.begin(), R.end());
18520b57cec5SDimitry Andric }
18530b57cec5SDimitry Andric 
18545ffd83dbSDimitry Andric /// An STL-style algorithm similar to std::for_each that applies a second
18555ffd83dbSDimitry Andric /// functor between every pair of elements.
18565ffd83dbSDimitry Andric ///
18575ffd83dbSDimitry Andric /// This provides the control flow logic to, for example, print a
18585ffd83dbSDimitry Andric /// comma-separated list:
18595ffd83dbSDimitry Andric /// \code
18605ffd83dbSDimitry Andric ///   interleave(names.begin(), names.end(),
18615ffd83dbSDimitry Andric ///              [&](StringRef name) { os << name; },
18625ffd83dbSDimitry Andric ///              [&] { os << ", "; });
18635ffd83dbSDimitry Andric /// \endcode
18645ffd83dbSDimitry Andric template <typename ForwardIterator, typename UnaryFunctor,
18655ffd83dbSDimitry Andric           typename NullaryFunctor,
18665ffd83dbSDimitry Andric           typename = typename std::enable_if<
18675ffd83dbSDimitry Andric               !std::is_constructible<StringRef, UnaryFunctor>::value &&
18685ffd83dbSDimitry Andric               !std::is_constructible<StringRef, NullaryFunctor>::value>::type>
18695ffd83dbSDimitry Andric inline void interleave(ForwardIterator begin, ForwardIterator end,
18705ffd83dbSDimitry Andric                        UnaryFunctor each_fn, NullaryFunctor between_fn) {
18715ffd83dbSDimitry Andric   if (begin == end)
18725ffd83dbSDimitry Andric     return;
18735ffd83dbSDimitry Andric   each_fn(*begin);
18745ffd83dbSDimitry Andric   ++begin;
18755ffd83dbSDimitry Andric   for (; begin != end; ++begin) {
18765ffd83dbSDimitry Andric     between_fn();
18775ffd83dbSDimitry Andric     each_fn(*begin);
18785ffd83dbSDimitry Andric   }
18795ffd83dbSDimitry Andric }
18805ffd83dbSDimitry Andric 
18815ffd83dbSDimitry Andric template <typename Container, typename UnaryFunctor, typename NullaryFunctor,
18825ffd83dbSDimitry Andric           typename = typename std::enable_if<
18835ffd83dbSDimitry Andric               !std::is_constructible<StringRef, UnaryFunctor>::value &&
18845ffd83dbSDimitry Andric               !std::is_constructible<StringRef, NullaryFunctor>::value>::type>
18855ffd83dbSDimitry Andric inline void interleave(const Container &c, UnaryFunctor each_fn,
18865ffd83dbSDimitry Andric                        NullaryFunctor between_fn) {
18875ffd83dbSDimitry Andric   interleave(c.begin(), c.end(), each_fn, between_fn);
18885ffd83dbSDimitry Andric }
18895ffd83dbSDimitry Andric 
18905ffd83dbSDimitry Andric /// Overload of interleave for the common case of string separator.
18915ffd83dbSDimitry Andric template <typename Container, typename UnaryFunctor, typename StreamT,
18925ffd83dbSDimitry Andric           typename T = detail::ValueOfRange<Container>>
18935ffd83dbSDimitry Andric inline void interleave(const Container &c, StreamT &os, UnaryFunctor each_fn,
18945ffd83dbSDimitry Andric                        const StringRef &separator) {
18955ffd83dbSDimitry Andric   interleave(c.begin(), c.end(), each_fn, [&] { os << separator; });
18965ffd83dbSDimitry Andric }
18975ffd83dbSDimitry Andric template <typename Container, typename StreamT,
18985ffd83dbSDimitry Andric           typename T = detail::ValueOfRange<Container>>
18995ffd83dbSDimitry Andric inline void interleave(const Container &c, StreamT &os,
19005ffd83dbSDimitry Andric                        const StringRef &separator) {
19015ffd83dbSDimitry Andric   interleave(
19025ffd83dbSDimitry Andric       c, os, [&](const T &a) { os << a; }, separator);
19035ffd83dbSDimitry Andric }
19045ffd83dbSDimitry Andric 
19055ffd83dbSDimitry Andric template <typename Container, typename UnaryFunctor, typename StreamT,
19065ffd83dbSDimitry Andric           typename T = detail::ValueOfRange<Container>>
19075ffd83dbSDimitry Andric inline void interleaveComma(const Container &c, StreamT &os,
19085ffd83dbSDimitry Andric                             UnaryFunctor each_fn) {
19095ffd83dbSDimitry Andric   interleave(c, os, each_fn, ", ");
19105ffd83dbSDimitry Andric }
19115ffd83dbSDimitry Andric template <typename Container, typename StreamT,
19125ffd83dbSDimitry Andric           typename T = detail::ValueOfRange<Container>>
19135ffd83dbSDimitry Andric inline void interleaveComma(const Container &c, StreamT &os) {
19145ffd83dbSDimitry Andric   interleaveComma(c, os, [&](const T &a) { os << a; });
19155ffd83dbSDimitry Andric }
19165ffd83dbSDimitry Andric 
19170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
19180b57cec5SDimitry Andric //     Extra additions to <memory>
19190b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
19200b57cec5SDimitry Andric 
19210b57cec5SDimitry Andric struct FreeDeleter {
19220b57cec5SDimitry Andric   void operator()(void* v) {
19230b57cec5SDimitry Andric     ::free(v);
19240b57cec5SDimitry Andric   }
19250b57cec5SDimitry Andric };
19260b57cec5SDimitry Andric 
19270b57cec5SDimitry Andric template<typename First, typename Second>
19280b57cec5SDimitry Andric struct pair_hash {
19290b57cec5SDimitry Andric   size_t operator()(const std::pair<First, Second> &P) const {
19300b57cec5SDimitry Andric     return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second);
19310b57cec5SDimitry Andric   }
19320b57cec5SDimitry Andric };
19330b57cec5SDimitry Andric 
19340b57cec5SDimitry Andric /// Binary functor that adapts to any other binary functor after dereferencing
19350b57cec5SDimitry Andric /// operands.
19360b57cec5SDimitry Andric template <typename T> struct deref {
19370b57cec5SDimitry Andric   T func;
19380b57cec5SDimitry Andric 
19390b57cec5SDimitry Andric   // Could be further improved to cope with non-derivable functors and
19400b57cec5SDimitry Andric   // non-binary functors (should be a variadic template member function
19410b57cec5SDimitry Andric   // operator()).
19425ffd83dbSDimitry Andric   template <typename A, typename B> auto operator()(A &lhs, B &rhs) const {
19430b57cec5SDimitry Andric     assert(lhs);
19440b57cec5SDimitry Andric     assert(rhs);
19450b57cec5SDimitry Andric     return func(*lhs, *rhs);
19460b57cec5SDimitry Andric   }
19470b57cec5SDimitry Andric };
19480b57cec5SDimitry Andric 
19490b57cec5SDimitry Andric namespace detail {
19500b57cec5SDimitry Andric 
19510b57cec5SDimitry Andric template <typename R> class enumerator_iter;
19520b57cec5SDimitry Andric 
19530b57cec5SDimitry Andric template <typename R> struct result_pair {
19540b57cec5SDimitry Andric   using value_reference =
19550b57cec5SDimitry Andric       typename std::iterator_traits<IterOfRange<R>>::reference;
19560b57cec5SDimitry Andric 
19570b57cec5SDimitry Andric   friend class enumerator_iter<R>;
19580b57cec5SDimitry Andric 
19590b57cec5SDimitry Andric   result_pair() = default;
19600b57cec5SDimitry Andric   result_pair(std::size_t Index, IterOfRange<R> Iter)
19610b57cec5SDimitry Andric       : Index(Index), Iter(Iter) {}
19620b57cec5SDimitry Andric 
1963fe6060f1SDimitry Andric   result_pair(const result_pair<R> &Other)
1964480093f4SDimitry Andric       : Index(Other.Index), Iter(Other.Iter) {}
1965fe6060f1SDimitry Andric   result_pair &operator=(const result_pair &Other) {
19660b57cec5SDimitry Andric     Index = Other.Index;
19670b57cec5SDimitry Andric     Iter = Other.Iter;
19680b57cec5SDimitry Andric     return *this;
19690b57cec5SDimitry Andric   }
19700b57cec5SDimitry Andric 
19710b57cec5SDimitry Andric   std::size_t index() const { return Index; }
1972349cc55cSDimitry Andric   value_reference value() const { return *Iter; }
19730b57cec5SDimitry Andric 
19740b57cec5SDimitry Andric private:
19750b57cec5SDimitry Andric   std::size_t Index = std::numeric_limits<std::size_t>::max();
19760b57cec5SDimitry Andric   IterOfRange<R> Iter;
19770b57cec5SDimitry Andric };
19780b57cec5SDimitry Andric 
19790b57cec5SDimitry Andric template <typename R>
19800b57cec5SDimitry Andric class enumerator_iter
1981349cc55cSDimitry Andric     : public iterator_facade_base<enumerator_iter<R>, std::forward_iterator_tag,
1982349cc55cSDimitry Andric                                   const result_pair<R>> {
19830b57cec5SDimitry Andric   using result_type = result_pair<R>;
19840b57cec5SDimitry Andric 
19850b57cec5SDimitry Andric public:
19860b57cec5SDimitry Andric   explicit enumerator_iter(IterOfRange<R> EndIter)
19870b57cec5SDimitry Andric       : Result(std::numeric_limits<size_t>::max(), EndIter) {}
19880b57cec5SDimitry Andric 
19890b57cec5SDimitry Andric   enumerator_iter(std::size_t Index, IterOfRange<R> Iter)
19900b57cec5SDimitry Andric       : Result(Index, Iter) {}
19910b57cec5SDimitry Andric 
19920b57cec5SDimitry Andric   const result_type &operator*() const { return Result; }
19930b57cec5SDimitry Andric 
1994fe6060f1SDimitry Andric   enumerator_iter &operator++() {
19950b57cec5SDimitry Andric     assert(Result.Index != std::numeric_limits<size_t>::max());
19960b57cec5SDimitry Andric     ++Result.Iter;
19970b57cec5SDimitry Andric     ++Result.Index;
19980b57cec5SDimitry Andric     return *this;
19990b57cec5SDimitry Andric   }
20000b57cec5SDimitry Andric 
2001fe6060f1SDimitry Andric   bool operator==(const enumerator_iter &RHS) const {
20020b57cec5SDimitry Andric     // Don't compare indices here, only iterators.  It's possible for an end
20030b57cec5SDimitry Andric     // iterator to have different indices depending on whether it was created
20040b57cec5SDimitry Andric     // by calling std::end() versus incrementing a valid iterator.
20050b57cec5SDimitry Andric     return Result.Iter == RHS.Result.Iter;
20060b57cec5SDimitry Andric   }
20070b57cec5SDimitry Andric 
2008fe6060f1SDimitry Andric   enumerator_iter(const enumerator_iter &Other) : Result(Other.Result) {}
2009fe6060f1SDimitry Andric   enumerator_iter &operator=(const enumerator_iter &Other) {
20100b57cec5SDimitry Andric     Result = Other.Result;
20110b57cec5SDimitry Andric     return *this;
20120b57cec5SDimitry Andric   }
20130b57cec5SDimitry Andric 
20140b57cec5SDimitry Andric private:
20150b57cec5SDimitry Andric   result_type Result;
20160b57cec5SDimitry Andric };
20170b57cec5SDimitry Andric 
20180b57cec5SDimitry Andric template <typename R> class enumerator {
20190b57cec5SDimitry Andric public:
20200b57cec5SDimitry Andric   explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {}
20210b57cec5SDimitry Andric 
20220b57cec5SDimitry Andric   enumerator_iter<R> begin() {
20230b57cec5SDimitry Andric     return enumerator_iter<R>(0, std::begin(TheRange));
20240b57cec5SDimitry Andric   }
20254824e7fdSDimitry Andric   enumerator_iter<R> begin() const {
20264824e7fdSDimitry Andric     return enumerator_iter<R>(0, std::begin(TheRange));
20274824e7fdSDimitry Andric   }
20280b57cec5SDimitry Andric 
20290b57cec5SDimitry Andric   enumerator_iter<R> end() {
20300b57cec5SDimitry Andric     return enumerator_iter<R>(std::end(TheRange));
20310b57cec5SDimitry Andric   }
20324824e7fdSDimitry Andric   enumerator_iter<R> end() const {
20334824e7fdSDimitry Andric     return enumerator_iter<R>(std::end(TheRange));
20344824e7fdSDimitry Andric   }
20350b57cec5SDimitry Andric 
20360b57cec5SDimitry Andric private:
20370b57cec5SDimitry Andric   R TheRange;
20380b57cec5SDimitry Andric };
20390b57cec5SDimitry Andric 
20400b57cec5SDimitry Andric } // end namespace detail
20410b57cec5SDimitry Andric 
20420b57cec5SDimitry Andric /// Given an input range, returns a new range whose values are are pair (A,B)
20430b57cec5SDimitry Andric /// such that A is the 0-based index of the item in the sequence, and B is
20440b57cec5SDimitry Andric /// the value from the original sequence.  Example:
20450b57cec5SDimitry Andric ///
20460b57cec5SDimitry Andric /// std::vector<char> Items = {'A', 'B', 'C', 'D'};
20470b57cec5SDimitry Andric /// for (auto X : enumerate(Items)) {
20480b57cec5SDimitry Andric ///   printf("Item %d - %c\n", X.index(), X.value());
20490b57cec5SDimitry Andric /// }
20500b57cec5SDimitry Andric ///
20510b57cec5SDimitry Andric /// Output:
20520b57cec5SDimitry Andric ///   Item 0 - A
20530b57cec5SDimitry Andric ///   Item 1 - B
20540b57cec5SDimitry Andric ///   Item 2 - C
20550b57cec5SDimitry Andric ///   Item 3 - D
20560b57cec5SDimitry Andric ///
20570b57cec5SDimitry Andric template <typename R> detail::enumerator<R> enumerate(R &&TheRange) {
20580b57cec5SDimitry Andric   return detail::enumerator<R>(std::forward<R>(TheRange));
20590b57cec5SDimitry Andric }
20600b57cec5SDimitry Andric 
20610b57cec5SDimitry Andric namespace detail {
20620b57cec5SDimitry Andric 
20630b57cec5SDimitry Andric template <typename F, typename Tuple, std::size_t... I>
20645ffd83dbSDimitry Andric decltype(auto) apply_tuple_impl(F &&f, Tuple &&t, std::index_sequence<I...>) {
20650b57cec5SDimitry Andric   return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
20660b57cec5SDimitry Andric }
20670b57cec5SDimitry Andric 
20680b57cec5SDimitry Andric } // end namespace detail
20690b57cec5SDimitry Andric 
20700b57cec5SDimitry Andric /// Given an input tuple (a1, a2, ..., an), pass the arguments of the
20710b57cec5SDimitry Andric /// tuple variadically to f as if by calling f(a1, a2, ..., an) and
20720b57cec5SDimitry Andric /// return the result.
20730b57cec5SDimitry Andric template <typename F, typename Tuple>
20745ffd83dbSDimitry Andric decltype(auto) apply_tuple(F &&f, Tuple &&t) {
20758bcb0991SDimitry Andric   using Indices = std::make_index_sequence<
20760b57cec5SDimitry Andric       std::tuple_size<typename std::decay<Tuple>::type>::value>;
20770b57cec5SDimitry Andric 
20780b57cec5SDimitry Andric   return detail::apply_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t),
20790b57cec5SDimitry Andric                                   Indices{});
20800b57cec5SDimitry Andric }
20810b57cec5SDimitry Andric 
2082349cc55cSDimitry Andric namespace detail {
2083349cc55cSDimitry Andric 
2084349cc55cSDimitry Andric template <typename Predicate, typename... Args>
2085349cc55cSDimitry Andric bool all_of_zip_predicate_first(Predicate &&P, Args &&...args) {
2086349cc55cSDimitry Andric   auto z = zip(args...);
2087349cc55cSDimitry Andric   auto it = z.begin();
2088349cc55cSDimitry Andric   auto end = z.end();
2089349cc55cSDimitry Andric   while (it != end) {
2090349cc55cSDimitry Andric     if (!apply_tuple([&](auto &&...args) { return P(args...); }, *it))
2091349cc55cSDimitry Andric       return false;
2092349cc55cSDimitry Andric     ++it;
2093349cc55cSDimitry Andric   }
2094349cc55cSDimitry Andric   return it.all_equals(end);
2095349cc55cSDimitry Andric }
2096349cc55cSDimitry Andric 
2097349cc55cSDimitry Andric // Just an adaptor to switch the order of argument and have the predicate before
2098349cc55cSDimitry Andric // the zipped inputs.
2099349cc55cSDimitry Andric template <typename... ArgsThenPredicate, size_t... InputIndexes>
2100349cc55cSDimitry Andric bool all_of_zip_predicate_last(
2101349cc55cSDimitry Andric     std::tuple<ArgsThenPredicate...> argsThenPredicate,
2102349cc55cSDimitry Andric     std::index_sequence<InputIndexes...>) {
2103349cc55cSDimitry Andric   auto constexpr OutputIndex =
2104349cc55cSDimitry Andric       std::tuple_size<decltype(argsThenPredicate)>::value - 1;
2105349cc55cSDimitry Andric   return all_of_zip_predicate_first(std::get<OutputIndex>(argsThenPredicate),
2106349cc55cSDimitry Andric                              std::get<InputIndexes>(argsThenPredicate)...);
2107349cc55cSDimitry Andric }
2108349cc55cSDimitry Andric 
2109349cc55cSDimitry Andric } // end namespace detail
2110349cc55cSDimitry Andric 
2111349cc55cSDimitry Andric /// Compare two zipped ranges using the provided predicate (as last argument).
2112349cc55cSDimitry Andric /// Return true if all elements satisfy the predicate and false otherwise.
2113349cc55cSDimitry Andric //  Return false if the zipped iterator aren't all at end (size mismatch).
2114349cc55cSDimitry Andric template <typename... ArgsAndPredicate>
2115349cc55cSDimitry Andric bool all_of_zip(ArgsAndPredicate &&...argsAndPredicate) {
2116349cc55cSDimitry Andric   return detail::all_of_zip_predicate_last(
2117349cc55cSDimitry Andric       std::forward_as_tuple(argsAndPredicate...),
2118349cc55cSDimitry Andric       std::make_index_sequence<sizeof...(argsAndPredicate) - 1>{});
2119349cc55cSDimitry Andric }
2120349cc55cSDimitry Andric 
21210b57cec5SDimitry Andric /// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N)
21220b57cec5SDimitry Andric /// time. Not meant for use with random-access iterators.
21235ffd83dbSDimitry Andric /// Can optionally take a predicate to filter lazily some items.
21245ffd83dbSDimitry Andric template <typename IterTy,
21255ffd83dbSDimitry Andric           typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)>
21260b57cec5SDimitry Andric bool hasNItems(
21270b57cec5SDimitry Andric     IterTy &&Begin, IterTy &&End, unsigned N,
21285ffd83dbSDimitry Andric     Pred &&ShouldBeCounted =
21295ffd83dbSDimitry Andric         [](const decltype(*std::declval<IterTy>()) &) { return true; },
21305ffd83dbSDimitry Andric     std::enable_if_t<
2131e8d8bef9SDimitry Andric         !std::is_base_of<std::random_access_iterator_tag,
2132e8d8bef9SDimitry Andric                          typename std::iterator_traits<std::remove_reference_t<
2133e8d8bef9SDimitry Andric                              decltype(Begin)>>::iterator_category>::value,
21345ffd83dbSDimitry Andric         void> * = nullptr) {
21355ffd83dbSDimitry Andric   for (; N; ++Begin) {
21360b57cec5SDimitry Andric     if (Begin == End)
21370b57cec5SDimitry Andric       return false; // Too few.
21385ffd83dbSDimitry Andric     N -= ShouldBeCounted(*Begin);
21395ffd83dbSDimitry Andric   }
21405ffd83dbSDimitry Andric   for (; Begin != End; ++Begin)
21415ffd83dbSDimitry Andric     if (ShouldBeCounted(*Begin))
21425ffd83dbSDimitry Andric       return false; // Too many.
21435ffd83dbSDimitry Andric   return true;
21440b57cec5SDimitry Andric }
21450b57cec5SDimitry Andric 
21460b57cec5SDimitry Andric /// Return true if the sequence [Begin, End) has N or more items. Runs in O(N)
21470b57cec5SDimitry Andric /// time. Not meant for use with random-access iterators.
21485ffd83dbSDimitry Andric /// Can optionally take a predicate to lazily filter some items.
21495ffd83dbSDimitry Andric template <typename IterTy,
21505ffd83dbSDimitry Andric           typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)>
21510b57cec5SDimitry Andric bool hasNItemsOrMore(
21520b57cec5SDimitry Andric     IterTy &&Begin, IterTy &&End, unsigned N,
21535ffd83dbSDimitry Andric     Pred &&ShouldBeCounted =
21545ffd83dbSDimitry Andric         [](const decltype(*std::declval<IterTy>()) &) { return true; },
21555ffd83dbSDimitry Andric     std::enable_if_t<
2156e8d8bef9SDimitry Andric         !std::is_base_of<std::random_access_iterator_tag,
2157e8d8bef9SDimitry Andric                          typename std::iterator_traits<std::remove_reference_t<
2158e8d8bef9SDimitry Andric                              decltype(Begin)>>::iterator_category>::value,
21595ffd83dbSDimitry Andric         void> * = nullptr) {
21605ffd83dbSDimitry Andric   for (; N; ++Begin) {
21610b57cec5SDimitry Andric     if (Begin == End)
21620b57cec5SDimitry Andric       return false; // Too few.
21635ffd83dbSDimitry Andric     N -= ShouldBeCounted(*Begin);
21645ffd83dbSDimitry Andric   }
21650b57cec5SDimitry Andric   return true;
21660b57cec5SDimitry Andric }
21670b57cec5SDimitry Andric 
21685ffd83dbSDimitry Andric /// Returns true if the sequence [Begin, End) has N or less items. Can
21695ffd83dbSDimitry Andric /// optionally take a predicate to lazily filter some items.
21705ffd83dbSDimitry Andric template <typename IterTy,
21715ffd83dbSDimitry Andric           typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)>
21725ffd83dbSDimitry Andric bool hasNItemsOrLess(
21735ffd83dbSDimitry Andric     IterTy &&Begin, IterTy &&End, unsigned N,
21745ffd83dbSDimitry Andric     Pred &&ShouldBeCounted = [](const decltype(*std::declval<IterTy>()) &) {
21755ffd83dbSDimitry Andric       return true;
21765ffd83dbSDimitry Andric     }) {
21775ffd83dbSDimitry Andric   assert(N != std::numeric_limits<unsigned>::max());
21785ffd83dbSDimitry Andric   return !hasNItemsOrMore(Begin, End, N + 1, ShouldBeCounted);
21795ffd83dbSDimitry Andric }
21805ffd83dbSDimitry Andric 
21815ffd83dbSDimitry Andric /// Returns true if the given container has exactly N items
21825ffd83dbSDimitry Andric template <typename ContainerTy> bool hasNItems(ContainerTy &&C, unsigned N) {
21835ffd83dbSDimitry Andric   return hasNItems(std::begin(C), std::end(C), N);
21845ffd83dbSDimitry Andric }
21855ffd83dbSDimitry Andric 
21865ffd83dbSDimitry Andric /// Returns true if the given container has N or more items
21875ffd83dbSDimitry Andric template <typename ContainerTy>
21885ffd83dbSDimitry Andric bool hasNItemsOrMore(ContainerTy &&C, unsigned N) {
21895ffd83dbSDimitry Andric   return hasNItemsOrMore(std::begin(C), std::end(C), N);
21905ffd83dbSDimitry Andric }
21915ffd83dbSDimitry Andric 
21925ffd83dbSDimitry Andric /// Returns true if the given container has N or less items
21935ffd83dbSDimitry Andric template <typename ContainerTy>
21945ffd83dbSDimitry Andric bool hasNItemsOrLess(ContainerTy &&C, unsigned N) {
21955ffd83dbSDimitry Andric   return hasNItemsOrLess(std::begin(C), std::end(C), N);
21965ffd83dbSDimitry Andric }
21975ffd83dbSDimitry Andric 
21980b57cec5SDimitry Andric /// Returns a raw pointer that represents the same address as the argument.
21990b57cec5SDimitry Andric ///
22005ffd83dbSDimitry Andric /// This implementation can be removed once we move to C++20 where it's defined
22015ffd83dbSDimitry Andric /// as std::to_address().
22020b57cec5SDimitry Andric ///
22030b57cec5SDimitry Andric /// The std::pointer_traits<>::to_address(p) variations of these overloads has
22040b57cec5SDimitry Andric /// not been implemented.
22055ffd83dbSDimitry Andric template <class Ptr> auto to_address(const Ptr &P) { return P.operator->(); }
22060b57cec5SDimitry Andric template <class T> constexpr T *to_address(T *P) { return P; }
22070b57cec5SDimitry Andric 
22080b57cec5SDimitry Andric } // end namespace llvm
22090b57cec5SDimitry Andric 
22100b57cec5SDimitry Andric #endif // LLVM_ADT_STLEXTRAS_H
2211