File indexing completed on 2026-05-10 08:43:09
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017 #ifndef LLVM_ADT_STLEXTRAS_H
0018 #define LLVM_ADT_STLEXTRAS_H
0019
0020 #include "llvm/ADT/ADL.h"
0021 #include "llvm/ADT/Hashing.h"
0022 #include "llvm/ADT/STLForwardCompat.h"
0023 #include "llvm/ADT/STLFunctionalExtras.h"
0024 #include "llvm/ADT/iterator.h"
0025 #include "llvm/ADT/iterator_range.h"
0026 #include "llvm/Config/abi-breaking.h"
0027 #include "llvm/Support/ErrorHandling.h"
0028 #include <algorithm>
0029 #include <cassert>
0030 #include <cstddef>
0031 #include <cstdint>
0032 #include <cstdlib>
0033 #include <functional>
0034 #include <initializer_list>
0035 #include <iterator>
0036 #include <limits>
0037 #include <memory>
0038 #include <optional>
0039 #include <tuple>
0040 #include <type_traits>
0041 #include <utility>
0042
0043 #ifdef EXPENSIVE_CHECKS
0044 #include <random> // for std::mt19937
0045 #endif
0046
0047 namespace llvm {
0048
0049
0050
0051
0052
0053 template <typename T> struct make_const_ptr {
0054 using type = std::add_pointer_t<std::add_const_t<T>>;
0055 };
0056
0057 template <typename T> struct make_const_ref {
0058 using type = std::add_lvalue_reference_t<std::add_const_t<T>>;
0059 };
0060
0061 namespace detail {
0062 template <class, template <class...> class Op, class... Args> struct detector {
0063 using value_t = std::false_type;
0064 };
0065 template <template <class...> class Op, class... Args>
0066 struct detector<std::void_t<Op<Args...>>, Op, Args...> {
0067 using value_t = std::true_type;
0068 };
0069 }
0070
0071
0072
0073
0074
0075
0076
0077
0078 template <template <class...> class Op, class... Args>
0079 using is_detected = typename detail::detector<void, Op, Args...>::value_t;
0080
0081
0082
0083
0084
0085 template <typename T, bool isClass = std::is_class<T>::value>
0086 struct function_traits : public function_traits<decltype(&T::operator())> {};
0087
0088
0089 template <typename ClassType, typename ReturnType, typename... Args>
0090 struct function_traits<ReturnType (ClassType::*)(Args...) const, false> {
0091
0092 enum { num_args = sizeof...(Args) };
0093
0094
0095 using result_t = ReturnType;
0096
0097
0098 template <size_t Index>
0099 using arg_t = std::tuple_element_t<Index, std::tuple<Args...>>;
0100 };
0101
0102 template <typename ClassType, typename ReturnType, typename... Args>
0103 struct function_traits<ReturnType (ClassType::*)(Args...), false>
0104 : public function_traits<ReturnType (ClassType::*)(Args...) const> {};
0105
0106 template <typename ReturnType, typename... Args>
0107 struct function_traits<ReturnType (*)(Args...), false> {
0108
0109 enum { num_args = sizeof...(Args) };
0110
0111
0112 using result_t = ReturnType;
0113
0114
0115 template <size_t i>
0116 using arg_t = std::tuple_element_t<i, std::tuple<Args...>>;
0117 };
0118 template <typename ReturnType, typename... Args>
0119 struct function_traits<ReturnType (*const)(Args...), false>
0120 : public function_traits<ReturnType (*)(Args...)> {};
0121
0122 template <typename ReturnType, typename... Args>
0123 struct function_traits<ReturnType (&)(Args...), false>
0124 : public function_traits<ReturnType (*)(Args...)> {};
0125
0126
0127
0128 template <typename T, typename... Ts>
0129 using is_one_of = std::disjunction<std::is_same<T, Ts>...>;
0130
0131
0132
0133 template <typename T, typename... Ts>
0134 using are_base_of = std::conjunction<std::is_base_of<T, Ts>...>;
0135
0136 namespace detail {
0137 template <typename T, typename... Us> struct TypesAreDistinct;
0138 template <typename T, typename... Us>
0139 struct TypesAreDistinct
0140 : std::integral_constant<bool, !is_one_of<T, Us...>::value &&
0141 TypesAreDistinct<Us...>::value> {};
0142 template <typename T> struct TypesAreDistinct<T> : std::true_type {};
0143 }
0144
0145
0146
0147
0148
0149
0150
0151
0152 template <typename... Ts> struct TypesAreDistinct;
0153 template <> struct TypesAreDistinct<> : std::true_type {};
0154 template <typename... Ts>
0155 struct TypesAreDistinct
0156 : std::integral_constant<bool, detail::TypesAreDistinct<Ts...>::value> {};
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168 template <typename T, typename... Us> struct FirstIndexOfType;
0169 template <typename T, typename U, typename... Us>
0170 struct FirstIndexOfType<T, U, Us...>
0171 : std::integral_constant<size_t, 1 + FirstIndexOfType<T, Us...>::value> {};
0172 template <typename T, typename... Us>
0173 struct FirstIndexOfType<T, T, Us...> : std::integral_constant<size_t, 0> {};
0174
0175
0176
0177
0178 template <size_t I, typename... Ts>
0179 using TypeAtIndex = std::tuple_element_t<I, std::tuple<Ts...>>;
0180
0181
0182
0183 template <typename EnumTy1, typename EnumTy2,
0184 typename UT1 = std::enable_if_t<std::is_enum<EnumTy1>::value,
0185 std::underlying_type_t<EnumTy1>>,
0186 typename UT2 = std::enable_if_t<std::is_enum<EnumTy2>::value,
0187 std::underlying_type_t<EnumTy2>>>
0188 constexpr auto addEnumValues(EnumTy1 LHS, EnumTy2 RHS) {
0189 return static_cast<UT1>(LHS) + static_cast<UT2>(RHS);
0190 }
0191
0192
0193
0194
0195
0196 namespace callable_detail {
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208 template <typename T,
0209 bool = std::is_function_v<std::remove_pointer_t<remove_cvref_t<T>>>>
0210 class Callable {
0211 using value_type = std::remove_reference_t<T>;
0212 using reference = value_type &;
0213 using const_reference = value_type const &;
0214
0215 std::optional<value_type> Obj;
0216
0217 static_assert(!std::is_pointer_v<value_type>,
0218 "Pointers to non-functions are not callable.");
0219
0220 public:
0221 Callable() = default;
0222 Callable(T const &O) : Obj(std::in_place, O) {}
0223
0224 Callable(Callable const &Other) = default;
0225 Callable(Callable &&Other) = default;
0226
0227 Callable &operator=(Callable const &Other) {
0228 Obj = std::nullopt;
0229 if (Other.Obj)
0230 Obj.emplace(*Other.Obj);
0231 return *this;
0232 }
0233
0234 Callable &operator=(Callable &&Other) {
0235 Obj = std::nullopt;
0236 if (Other.Obj)
0237 Obj.emplace(std::move(*Other.Obj));
0238 return *this;
0239 }
0240
0241 template <typename... Pn,
0242 std::enable_if_t<std::is_invocable_v<T, Pn...>, int> = 0>
0243 decltype(auto) operator()(Pn &&...Params) {
0244 return (*Obj)(std::forward<Pn>(Params)...);
0245 }
0246
0247 template <typename... Pn,
0248 std::enable_if_t<std::is_invocable_v<T const, Pn...>, int> = 0>
0249 decltype(auto) operator()(Pn &&...Params) const {
0250 return (*Obj)(std::forward<Pn>(Params)...);
0251 }
0252
0253 bool valid() const { return Obj != std::nullopt; }
0254 bool reset() { return Obj = std::nullopt; }
0255
0256 operator reference() { return *Obj; }
0257 operator const_reference() const { return *Obj; }
0258 };
0259
0260
0261
0262 template <typename T> class Callable<T, true> {
0263 static constexpr bool IsPtr = std::is_pointer_v<remove_cvref_t<T>>;
0264
0265 using StorageT = std::conditional_t<IsPtr, T, std::remove_reference_t<T> *>;
0266 using CastT = std::conditional_t<IsPtr, T, T &>;
0267
0268 private:
0269 StorageT Func = nullptr;
0270
0271 private:
0272 template <typename In> static constexpr auto convertIn(In &&I) {
0273 if constexpr (IsPtr) {
0274
0275 return I;
0276 } else {
0277
0278 return &I;
0279 }
0280 }
0281
0282 public:
0283 Callable() = default;
0284
0285
0286
0287
0288
0289 template <
0290 typename FnPtrOrRef,
0291 std::enable_if_t<
0292 !std::is_same_v<remove_cvref_t<FnPtrOrRef>, Callable>, int
0293 > = 0
0294 >
0295 Callable(FnPtrOrRef &&F) : Func(convertIn(F)) {}
0296
0297 template <typename... Pn,
0298 std::enable_if_t<std::is_invocable_v<T, Pn...>, int> = 0>
0299 decltype(auto) operator()(Pn &&...Params) const {
0300 return Func(std::forward<Pn>(Params)...);
0301 }
0302
0303 bool valid() const { return Func != nullptr; }
0304 void reset() { Func = nullptr; }
0305
0306 operator T const &() const {
0307 if constexpr (IsPtr) {
0308
0309 return Func;
0310 } else {
0311 static_assert(std::is_reference_v<T>,
0312 "Expected a reference to a function.");
0313
0314 return *Func;
0315 }
0316 }
0317 };
0318
0319 }
0320
0321
0322 template <typename ContainerTy> bool hasSingleElement(ContainerTy &&C) {
0323 auto B = std::begin(C), E = std::end(C);
0324 return B != E && std::next(B) == E;
0325 }
0326
0327
0328
0329 template <typename T> auto drop_begin(T &&RangeOrContainer, size_t N = 1) {
0330 return make_range(std::next(adl_begin(RangeOrContainer), N),
0331 adl_end(RangeOrContainer));
0332 }
0333
0334
0335
0336 template <typename T> auto drop_end(T &&RangeOrContainer, size_t N = 1) {
0337 return make_range(adl_begin(RangeOrContainer),
0338 std::prev(adl_end(RangeOrContainer), N));
0339 }
0340
0341
0342
0343
0344 template <typename ItTy, typename FuncTy,
0345 typename ReferenceTy =
0346 decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))>
0347 class mapped_iterator
0348 : public iterator_adaptor_base<
0349 mapped_iterator<ItTy, FuncTy>, ItTy,
0350 typename std::iterator_traits<ItTy>::iterator_category,
0351 std::remove_reference_t<ReferenceTy>,
0352 typename std::iterator_traits<ItTy>::difference_type,
0353 std::remove_reference_t<ReferenceTy> *, ReferenceTy> {
0354 public:
0355 mapped_iterator() = default;
0356 mapped_iterator(ItTy U, FuncTy F)
0357 : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {}
0358
0359 ItTy getCurrent() { return this->I; }
0360
0361 const FuncTy &getFunction() const { return F; }
0362
0363 ReferenceTy operator*() const { return F(*this->I); }
0364
0365 private:
0366 callable_detail::Callable<FuncTy> F{};
0367 };
0368
0369
0370
0371 template <class ItTy, class FuncTy>
0372 inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) {
0373 return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F));
0374 }
0375
0376 template <class ContainerTy, class FuncTy>
0377 auto map_range(ContainerTy &&C, FuncTy F) {
0378 return make_range(map_iterator(std::begin(C), F),
0379 map_iterator(std::end(C), F));
0380 }
0381
0382
0383
0384
0385
0386
0387 template <typename DerivedT, typename ItTy, typename ReferenceTy>
0388 class mapped_iterator_base
0389 : public iterator_adaptor_base<
0390 DerivedT, ItTy,
0391 typename std::iterator_traits<ItTy>::iterator_category,
0392 std::remove_reference_t<ReferenceTy>,
0393 typename std::iterator_traits<ItTy>::difference_type,
0394 std::remove_reference_t<ReferenceTy> *, ReferenceTy> {
0395 public:
0396 using BaseT = mapped_iterator_base;
0397
0398 mapped_iterator_base(ItTy U)
0399 : mapped_iterator_base::iterator_adaptor_base(std::move(U)) {}
0400
0401 ItTy getCurrent() { return this->I; }
0402
0403 ReferenceTy operator*() const {
0404 return static_cast<const DerivedT &>(*this).mapElement(*this->I);
0405 }
0406 };
0407
0408 namespace detail {
0409 template <typename Range>
0410 using check_has_free_function_rbegin =
0411 decltype(adl_rbegin(std::declval<Range &>()));
0412
0413 template <typename Range>
0414 static constexpr bool HasFreeFunctionRBegin =
0415 is_detected<check_has_free_function_rbegin, Range>::value;
0416 }
0417
0418
0419
0420 template <typename ContainerTy> [[nodiscard]] auto reverse(ContainerTy &&C) {
0421 if constexpr (detail::HasFreeFunctionRBegin<ContainerTy>)
0422 return make_range(adl_rbegin(C), adl_rend(C));
0423 else
0424 return make_range(std::make_reverse_iterator(adl_end(C)),
0425 std::make_reverse_iterator(adl_begin(C)));
0426 }
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443
0444 template <typename WrappedIteratorT, typename PredicateT, typename IterTag>
0445 class filter_iterator_base
0446 : public iterator_adaptor_base<
0447 filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
0448 WrappedIteratorT,
0449 std::common_type_t<IterTag,
0450 typename std::iterator_traits<
0451 WrappedIteratorT>::iterator_category>> {
0452 using BaseT = typename filter_iterator_base::iterator_adaptor_base;
0453
0454 protected:
0455 WrappedIteratorT End;
0456 PredicateT Pred;
0457
0458 void findNextValid() {
0459 while (this->I != End && !Pred(*this->I))
0460 BaseT::operator++();
0461 }
0462
0463 filter_iterator_base() = default;
0464
0465
0466
0467
0468 filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End,
0469 PredicateT Pred)
0470 : BaseT(Begin), End(End), Pred(Pred) {
0471 findNextValid();
0472 }
0473
0474 public:
0475 using BaseT::operator++;
0476
0477 filter_iterator_base &operator++() {
0478 BaseT::operator++();
0479 findNextValid();
0480 return *this;
0481 }
0482
0483 decltype(auto) operator*() const {
0484 assert(BaseT::wrapped() != End && "Cannot dereference end iterator!");
0485 return BaseT::operator*();
0486 }
0487
0488 decltype(auto) operator->() const {
0489 assert(BaseT::wrapped() != End && "Cannot dereference end iterator!");
0490 return BaseT::operator->();
0491 }
0492 };
0493
0494
0495 template <typename WrappedIteratorT, typename PredicateT,
0496 typename IterTag = std::forward_iterator_tag>
0497 class filter_iterator_impl
0498 : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> {
0499 public:
0500 filter_iterator_impl() = default;
0501
0502 filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
0503 PredicateT Pred)
0504 : filter_iterator_impl::filter_iterator_base(Begin, End, Pred) {}
0505 };
0506
0507
0508 template <typename WrappedIteratorT, typename PredicateT>
0509 class filter_iterator_impl<WrappedIteratorT, PredicateT,
0510 std::bidirectional_iterator_tag>
0511 : public filter_iterator_base<WrappedIteratorT, PredicateT,
0512 std::bidirectional_iterator_tag> {
0513 using BaseT = typename filter_iterator_impl::filter_iterator_base;
0514
0515 void findPrevValid() {
0516 while (!this->Pred(*this->I))
0517 BaseT::operator--();
0518 }
0519
0520 public:
0521 using BaseT::operator--;
0522
0523 filter_iterator_impl() = default;
0524
0525 filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
0526 PredicateT Pred)
0527 : BaseT(Begin, End, Pred) {}
0528
0529 filter_iterator_impl &operator--() {
0530 BaseT::operator--();
0531 findPrevValid();
0532 return *this;
0533 }
0534 };
0535
0536 namespace detail {
0537
0538 template <bool is_bidirectional> struct fwd_or_bidi_tag_impl {
0539 using type = std::forward_iterator_tag;
0540 };
0541
0542 template <> struct fwd_or_bidi_tag_impl<true> {
0543 using type = std::bidirectional_iterator_tag;
0544 };
0545
0546
0547
0548
0549 template <typename IterT> struct fwd_or_bidi_tag {
0550 using type = typename fwd_or_bidi_tag_impl<std::is_base_of<
0551 std::bidirectional_iterator_tag,
0552 typename std::iterator_traits<IterT>::iterator_category>::value>::type;
0553 };
0554
0555 }
0556
0557
0558
0559 template <typename WrappedIteratorT, typename PredicateT>
0560 using filter_iterator = filter_iterator_impl<
0561 WrappedIteratorT, PredicateT,
0562 typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>;
0563
0564
0565
0566
0567
0568
0569
0570
0571 template <typename RangeT, typename PredicateT>
0572 iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>>
0573 make_filter_range(RangeT &&Range, PredicateT Pred) {
0574 using FilterIteratorT =
0575 filter_iterator<detail::IterOfRange<RangeT>, PredicateT>;
0576 return make_range(
0577 FilterIteratorT(std::begin(std::forward<RangeT>(Range)),
0578 std::end(std::forward<RangeT>(Range)), Pred),
0579 FilterIteratorT(std::end(std::forward<RangeT>(Range)),
0580 std::end(std::forward<RangeT>(Range)), Pred));
0581 }
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600 template <typename WrappedIteratorT>
0601 class early_inc_iterator_impl
0602 : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
0603 WrappedIteratorT, std::input_iterator_tag> {
0604 using BaseT = typename early_inc_iterator_impl::iterator_adaptor_base;
0605
0606 using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer;
0607
0608 protected:
0609 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0610 bool IsEarlyIncremented = false;
0611 #endif
0612
0613 public:
0614 early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {}
0615
0616 using BaseT::operator*;
0617 decltype(*std::declval<WrappedIteratorT>()) operator*() {
0618 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0619 assert(!IsEarlyIncremented && "Cannot dereference twice!");
0620 IsEarlyIncremented = true;
0621 #endif
0622 return *(this->I)++;
0623 }
0624
0625 using BaseT::operator++;
0626 early_inc_iterator_impl &operator++() {
0627 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0628 assert(IsEarlyIncremented && "Cannot increment before dereferencing!");
0629 IsEarlyIncremented = false;
0630 #endif
0631 return *this;
0632 }
0633
0634 friend bool operator==(const early_inc_iterator_impl &LHS,
0635 const early_inc_iterator_impl &RHS) {
0636 #if LLVM_ENABLE_ABI_BREAKING_CHECKS
0637 assert(!LHS.IsEarlyIncremented && "Cannot compare after dereferencing!");
0638 #endif
0639 return (const BaseT &)LHS == (const BaseT &)RHS;
0640 }
0641 };
0642
0643
0644
0645
0646
0647
0648
0649
0650
0651
0652
0653
0654
0655 template <typename RangeT>
0656 iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>>
0657 make_early_inc_range(RangeT &&Range) {
0658 using EarlyIncIteratorT =
0659 early_inc_iterator_impl<detail::IterOfRange<RangeT>>;
0660 return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))),
0661 EarlyIncIteratorT(std::end(std::forward<RangeT>(Range))));
0662 }
0663
0664
0665 template <typename R, typename UnaryPredicate>
0666 bool all_of(R &&range, UnaryPredicate P);
0667
0668 template <typename R, typename UnaryPredicate>
0669 bool any_of(R &&range, UnaryPredicate P);
0670
0671 template <typename T> bool all_equal(std::initializer_list<T> Values);
0672
0673 template <typename R> constexpr size_t range_size(R &&Range);
0674
0675 namespace detail {
0676
0677 using std::declval;
0678
0679
0680
0681 template<typename... Iters> struct ZipTupleType {
0682 using type = std::tuple<decltype(*declval<Iters>())...>;
0683 };
0684
0685 template <typename ZipType, typename ReferenceTupleType, typename... Iters>
0686 using zip_traits = iterator_facade_base<
0687 ZipType,
0688 std::common_type_t<
0689 std::bidirectional_iterator_tag,
0690 typename std::iterator_traits<Iters>::iterator_category...>,
0691
0692 ReferenceTupleType,
0693 typename std::iterator_traits<
0694 std::tuple_element_t<0, std::tuple<Iters...>>>::difference_type,
0695
0696
0697
0698
0699 ReferenceTupleType *, ReferenceTupleType>;
0700
0701 template <typename ZipType, typename ReferenceTupleType, typename... Iters>
0702 struct zip_common : public zip_traits<ZipType, ReferenceTupleType, Iters...> {
0703 using Base = zip_traits<ZipType, ReferenceTupleType, Iters...>;
0704 using IndexSequence = std::index_sequence_for<Iters...>;
0705 using value_type = typename Base::value_type;
0706
0707 std::tuple<Iters...> iterators;
0708
0709 protected:
0710 template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const {
0711 return value_type(*std::get<Ns>(iterators)...);
0712 }
0713
0714 template <size_t... Ns> void tup_inc(std::index_sequence<Ns...>) {
0715 (++std::get<Ns>(iterators), ...);
0716 }
0717
0718 template <size_t... Ns> void tup_dec(std::index_sequence<Ns...>) {
0719 (--std::get<Ns>(iterators), ...);
0720 }
0721
0722 template <size_t... Ns>
0723 bool test_all_equals(const zip_common &other,
0724 std::index_sequence<Ns...>) const {
0725 return ((std::get<Ns>(this->iterators) == std::get<Ns>(other.iterators)) &&
0726 ...);
0727 }
0728
0729 public:
0730 zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {}
0731
0732 value_type operator*() const { return deref(IndexSequence{}); }
0733
0734 ZipType &operator++() {
0735 tup_inc(IndexSequence{});
0736 return static_cast<ZipType &>(*this);
0737 }
0738
0739 ZipType &operator--() {
0740 static_assert(Base::IsBidirectional,
0741 "All inner iterators must be at least bidirectional.");
0742 tup_dec(IndexSequence{});
0743 return static_cast<ZipType &>(*this);
0744 }
0745
0746
0747 bool all_equals(zip_common &other) {
0748 return test_all_equals(other, IndexSequence{});
0749 }
0750 };
0751
0752 template <typename... Iters>
0753 struct zip_first : zip_common<zip_first<Iters...>,
0754 typename ZipTupleType<Iters...>::type, Iters...> {
0755 using zip_common<zip_first, typename ZipTupleType<Iters...>::type,
0756 Iters...>::zip_common;
0757
0758 bool operator==(const zip_first &other) const {
0759 return std::get<0>(this->iterators) == std::get<0>(other.iterators);
0760 }
0761 };
0762
0763 template <typename... Iters>
0764 struct zip_shortest
0765 : zip_common<zip_shortest<Iters...>, typename ZipTupleType<Iters...>::type,
0766 Iters...> {
0767 using zip_common<zip_shortest, typename ZipTupleType<Iters...>::type,
0768 Iters...>::zip_common;
0769
0770 bool operator==(const zip_shortest &other) const {
0771 return any_iterator_equals(other, std::index_sequence_for<Iters...>{});
0772 }
0773
0774 private:
0775 template <size_t... Ns>
0776 bool any_iterator_equals(const zip_shortest &other,
0777 std::index_sequence<Ns...>) const {
0778 return ((std::get<Ns>(this->iterators) == std::get<Ns>(other.iterators)) ||
0779 ...);
0780 }
0781 };
0782
0783
0784 template <template <typename...> class ItType, typename TupleStorageType,
0785 typename IndexSequence>
0786 struct ZippyIteratorTuple;
0787
0788
0789 template <template <typename...> class ItType, typename... Args,
0790 std::size_t... Ns>
0791 struct ZippyIteratorTuple<ItType, std::tuple<Args...>,
0792 std::index_sequence<Ns...>> {
0793 using type = ItType<decltype(adl_begin(
0794 std::get<Ns>(declval<std::tuple<Args...> &>())))...>;
0795 };
0796
0797
0798 template <template <typename...> class ItType, typename... Args,
0799 std::size_t... Ns>
0800 struct ZippyIteratorTuple<ItType, const std::tuple<Args...>,
0801 std::index_sequence<Ns...>> {
0802 using type = ItType<decltype(adl_begin(
0803 std::get<Ns>(declval<const std::tuple<Args...> &>())))...>;
0804 };
0805
0806 template <template <typename...> class ItType, typename... Args> class zippy {
0807 private:
0808 std::tuple<Args...> storage;
0809 using IndexSequence = std::index_sequence_for<Args...>;
0810
0811 public:
0812 using iterator = typename ZippyIteratorTuple<ItType, decltype(storage),
0813 IndexSequence>::type;
0814 using const_iterator =
0815 typename ZippyIteratorTuple<ItType, const decltype(storage),
0816 IndexSequence>::type;
0817 using iterator_category = typename iterator::iterator_category;
0818 using value_type = typename iterator::value_type;
0819 using difference_type = typename iterator::difference_type;
0820 using pointer = typename iterator::pointer;
0821 using reference = typename iterator::reference;
0822 using const_reference = typename const_iterator::reference;
0823
0824 zippy(Args &&...args) : storage(std::forward<Args>(args)...) {}
0825
0826 const_iterator begin() const { return begin_impl(IndexSequence{}); }
0827 iterator begin() { return begin_impl(IndexSequence{}); }
0828 const_iterator end() const { return end_impl(IndexSequence{}); }
0829 iterator end() { return end_impl(IndexSequence{}); }
0830
0831 private:
0832 template <size_t... Ns>
0833 const_iterator begin_impl(std::index_sequence<Ns...>) const {
0834 return const_iterator(adl_begin(std::get<Ns>(storage))...);
0835 }
0836 template <size_t... Ns> iterator begin_impl(std::index_sequence<Ns...>) {
0837 return iterator(adl_begin(std::get<Ns>(storage))...);
0838 }
0839
0840 template <size_t... Ns>
0841 const_iterator end_impl(std::index_sequence<Ns...>) const {
0842 return const_iterator(adl_end(std::get<Ns>(storage))...);
0843 }
0844 template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) {
0845 return iterator(adl_end(std::get<Ns>(storage))...);
0846 }
0847 };
0848
0849 }
0850
0851
0852
0853 template <typename T, typename U, typename... Args>
0854 detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u,
0855 Args &&...args) {
0856 return detail::zippy<detail::zip_shortest, T, U, Args...>(
0857 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
0858 }
0859
0860
0861
0862
0863 template <typename T, typename U, typename... Args>
0864 detail::zippy<detail::zip_first, T, U, Args...> zip_equal(T &&t, U &&u,
0865 Args &&...args) {
0866 assert(all_equal({range_size(t), range_size(u), range_size(args)...}) &&
0867 "Iteratees do not have equal length");
0868 return detail::zippy<detail::zip_first, T, U, Args...>(
0869 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
0870 }
0871
0872
0873
0874
0875
0876 template <typename T, typename U, typename... Args>
0877 detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u,
0878 Args &&...args) {
0879 assert(range_size(t) <= std::min({range_size(u), range_size(args)...}) &&
0880 "First iteratee is not the shortest");
0881
0882 return detail::zippy<detail::zip_first, T, U, Args...>(
0883 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
0884 }
0885
0886 namespace detail {
0887 template <typename Iter>
0888 Iter next_or_end(const Iter &I, const Iter &End) {
0889 if (I == End)
0890 return End;
0891 return std::next(I);
0892 }
0893
0894 template <typename Iter>
0895 auto deref_or_none(const Iter &I, const Iter &End) -> std::optional<
0896 std::remove_const_t<std::remove_reference_t<decltype(*I)>>> {
0897 if (I == End)
0898 return std::nullopt;
0899 return *I;
0900 }
0901
0902 template <typename Iter> struct ZipLongestItemType {
0903 using type = std::optional<std::remove_const_t<
0904 std::remove_reference_t<decltype(*std::declval<Iter>())>>>;
0905 };
0906
0907 template <typename... Iters> struct ZipLongestTupleType {
0908 using type = std::tuple<typename ZipLongestItemType<Iters>::type...>;
0909 };
0910
0911 template <typename... Iters>
0912 class zip_longest_iterator
0913 : public iterator_facade_base<
0914 zip_longest_iterator<Iters...>,
0915 std::common_type_t<
0916 std::forward_iterator_tag,
0917 typename std::iterator_traits<Iters>::iterator_category...>,
0918 typename ZipLongestTupleType<Iters...>::type,
0919 typename std::iterator_traits<
0920 std::tuple_element_t<0, std::tuple<Iters...>>>::difference_type,
0921 typename ZipLongestTupleType<Iters...>::type *,
0922 typename ZipLongestTupleType<Iters...>::type> {
0923 public:
0924 using value_type = typename ZipLongestTupleType<Iters...>::type;
0925
0926 private:
0927 std::tuple<Iters...> iterators;
0928 std::tuple<Iters...> end_iterators;
0929
0930 template <size_t... Ns>
0931 bool test(const zip_longest_iterator<Iters...> &other,
0932 std::index_sequence<Ns...>) const {
0933 return ((std::get<Ns>(this->iterators) != std::get<Ns>(other.iterators)) ||
0934 ...);
0935 }
0936
0937 template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const {
0938 return value_type(
0939 deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
0940 }
0941
0942 template <size_t... Ns>
0943 decltype(iterators) tup_inc(std::index_sequence<Ns...>) const {
0944 return std::tuple<Iters...>(
0945 next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
0946 }
0947
0948 public:
0949 zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts)
0950 : iterators(std::forward<Iters>(ts.first)...),
0951 end_iterators(std::forward<Iters>(ts.second)...) {}
0952
0953 value_type operator*() const {
0954 return deref(std::index_sequence_for<Iters...>{});
0955 }
0956
0957 zip_longest_iterator<Iters...> &operator++() {
0958 iterators = tup_inc(std::index_sequence_for<Iters...>{});
0959 return *this;
0960 }
0961
0962 bool operator==(const zip_longest_iterator<Iters...> &other) const {
0963 return !test(other, std::index_sequence_for<Iters...>{});
0964 }
0965 };
0966
0967 template <typename... Args> class zip_longest_range {
0968 public:
0969 using iterator =
0970 zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>;
0971 using iterator_category = typename iterator::iterator_category;
0972 using value_type = typename iterator::value_type;
0973 using difference_type = typename iterator::difference_type;
0974 using pointer = typename iterator::pointer;
0975 using reference = typename iterator::reference;
0976
0977 private:
0978 std::tuple<Args...> ts;
0979
0980 template <size_t... Ns>
0981 iterator begin_impl(std::index_sequence<Ns...>) const {
0982 return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)),
0983 adl_end(std::get<Ns>(ts)))...);
0984 }
0985
0986 template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const {
0987 return iterator(std::make_pair(adl_end(std::get<Ns>(ts)),
0988 adl_end(std::get<Ns>(ts)))...);
0989 }
0990
0991 public:
0992 zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
0993
0994 iterator begin() const {
0995 return begin_impl(std::index_sequence_for<Args...>{});
0996 }
0997 iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); }
0998 };
0999 }
1000
1001
1002
1003
1004 template <typename T, typename U, typename... Args>
1005 detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u,
1006 Args &&... args) {
1007 return detail::zip_longest_range<T, U, Args...>(
1008 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
1009 }
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021 template <typename ValueT, typename... IterTs>
1022 class concat_iterator
1023 : public iterator_facade_base<concat_iterator<ValueT, IterTs...>,
1024 std::forward_iterator_tag, ValueT> {
1025 using BaseT = typename concat_iterator::iterator_facade_base;
1026
1027 static constexpr bool ReturnsByValue =
1028 !(std::is_reference_v<decltype(*std::declval<IterTs>())> && ...);
1029
1030 using reference_type =
1031 typename std::conditional_t<ReturnsByValue, ValueT, ValueT &>;
1032
1033 using handle_type =
1034 typename std::conditional_t<ReturnsByValue, std::optional<ValueT>,
1035 ValueT *>;
1036
1037
1038
1039
1040
1041
1042
1043 std::tuple<IterTs...> Begins;
1044 std::tuple<IterTs...> Ends;
1045
1046
1047
1048
1049
1050 template <size_t Index> bool incrementHelper() {
1051 auto &Begin = std::get<Index>(Begins);
1052 auto &End = std::get<Index>(Ends);
1053 if (Begin == End)
1054 return false;
1055
1056 ++Begin;
1057 return true;
1058 }
1059
1060
1061
1062
1063 template <size_t... Ns> void increment(std::index_sequence<Ns...>) {
1064
1065 bool (concat_iterator::*IncrementHelperFns[])() = {
1066 &concat_iterator::incrementHelper<Ns>...};
1067
1068
1069 for (auto &IncrementHelperFn : IncrementHelperFns)
1070 if ((this->*IncrementHelperFn)())
1071 return;
1072
1073 llvm_unreachable("Attempted to increment an end concat iterator!");
1074 }
1075
1076
1077
1078
1079 template <size_t Index> handle_type getHelper() const {
1080 auto &Begin = std::get<Index>(Begins);
1081 auto &End = std::get<Index>(Ends);
1082 if (Begin == End)
1083 return {};
1084
1085 if constexpr (ReturnsByValue)
1086 return *Begin;
1087 else
1088 return &*Begin;
1089 }
1090
1091
1092
1093
1094
1095 template <size_t... Ns> reference_type get(std::index_sequence<Ns...>) const {
1096
1097 handle_type (concat_iterator::*GetHelperFns[])()
1098 const = {&concat_iterator::getHelper<Ns>...};
1099
1100
1101 for (auto &GetHelperFn : GetHelperFns)
1102 if (auto P = (this->*GetHelperFn)())
1103 return *P;
1104
1105 llvm_unreachable("Attempted to get a pointer from an end concat iterator!");
1106 }
1107
1108 public:
1109
1110
1111
1112
1113 template <typename... RangeTs>
1114 explicit concat_iterator(RangeTs &&... Ranges)
1115 : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {}
1116
1117 using BaseT::operator++;
1118
1119 concat_iterator &operator++() {
1120 increment(std::index_sequence_for<IterTs...>());
1121 return *this;
1122 }
1123
1124 reference_type operator*() const {
1125 return get(std::index_sequence_for<IterTs...>());
1126 }
1127
1128 bool operator==(const concat_iterator &RHS) const {
1129 return Begins == RHS.Begins && Ends == RHS.Ends;
1130 }
1131 };
1132
1133 namespace detail {
1134
1135
1136
1137
1138
1139
1140 template <typename ValueT, typename... RangeTs> class concat_range {
1141 public:
1142 using iterator =
1143 concat_iterator<ValueT,
1144 decltype(std::begin(std::declval<RangeTs &>()))...>;
1145
1146 private:
1147 std::tuple<RangeTs...> Ranges;
1148
1149 template <size_t... Ns>
1150 iterator begin_impl(std::index_sequence<Ns...>) {
1151 return iterator(std::get<Ns>(Ranges)...);
1152 }
1153 template <size_t... Ns>
1154 iterator begin_impl(std::index_sequence<Ns...>) const {
1155 return iterator(std::get<Ns>(Ranges)...);
1156 }
1157 template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) {
1158 return iterator(make_range(std::end(std::get<Ns>(Ranges)),
1159 std::end(std::get<Ns>(Ranges)))...);
1160 }
1161 template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const {
1162 return iterator(make_range(std::end(std::get<Ns>(Ranges)),
1163 std::end(std::get<Ns>(Ranges)))...);
1164 }
1165
1166 public:
1167 concat_range(RangeTs &&... Ranges)
1168 : Ranges(std::forward<RangeTs>(Ranges)...) {}
1169
1170 iterator begin() {
1171 return begin_impl(std::index_sequence_for<RangeTs...>{});
1172 }
1173 iterator begin() const {
1174 return begin_impl(std::index_sequence_for<RangeTs...>{});
1175 }
1176 iterator end() {
1177 return end_impl(std::index_sequence_for<RangeTs...>{});
1178 }
1179 iterator end() const {
1180 return end_impl(std::index_sequence_for<RangeTs...>{});
1181 }
1182 };
1183
1184 }
1185
1186
1187
1188
1189
1190 template <typename ValueT, typename... RangeTs>
1191 [[nodiscard]] detail::concat_range<ValueT, RangeTs...>
1192 concat(RangeTs &&...Ranges) {
1193 static_assert(sizeof...(RangeTs) > 1,
1194 "Need more than one range to concatenate!");
1195 return detail::concat_range<ValueT, RangeTs...>(
1196 std::forward<RangeTs>(Ranges)...);
1197 }
1198
1199
1200
1201 template <typename DerivedT, typename BaseT, typename T,
1202 typename PointerT = T *, typename ReferenceT = T &>
1203 class indexed_accessor_iterator
1204 : public llvm::iterator_facade_base<DerivedT,
1205 std::random_access_iterator_tag, T,
1206 std::ptrdiff_t, PointerT, ReferenceT> {
1207 public:
1208 ptrdiff_t operator-(const indexed_accessor_iterator &rhs) const {
1209 assert(base == rhs.base && "incompatible iterators");
1210 return index - rhs.index;
1211 }
1212 bool operator==(const indexed_accessor_iterator &rhs) const {
1213 assert(base == rhs.base && "incompatible iterators");
1214 return index == rhs.index;
1215 }
1216 bool operator<(const indexed_accessor_iterator &rhs) const {
1217 assert(base == rhs.base && "incompatible iterators");
1218 return index < rhs.index;
1219 }
1220
1221 DerivedT &operator+=(ptrdiff_t offset) {
1222 this->index += offset;
1223 return static_cast<DerivedT &>(*this);
1224 }
1225 DerivedT &operator-=(ptrdiff_t offset) {
1226 this->index -= offset;
1227 return static_cast<DerivedT &>(*this);
1228 }
1229
1230
1231 ptrdiff_t getIndex() const { return index; }
1232
1233
1234 const BaseT &getBase() const { return base; }
1235
1236 protected:
1237 indexed_accessor_iterator(BaseT base, ptrdiff_t index)
1238 : base(base), index(index) {}
1239 BaseT base;
1240 ptrdiff_t index;
1241 };
1242
1243 namespace detail {
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254 template <typename DerivedT, typename BaseT, typename T,
1255 typename PointerT = T *, typename ReferenceT = T &>
1256 class indexed_accessor_range_base {
1257 public:
1258 using RangeBaseT = indexed_accessor_range_base;
1259
1260
1261 class iterator : public indexed_accessor_iterator<iterator, BaseT, T,
1262 PointerT, ReferenceT> {
1263 public:
1264
1265 ReferenceT operator*() const {
1266 return DerivedT::dereference_iterator(this->getBase(), this->getIndex());
1267 }
1268
1269 private:
1270 iterator(BaseT owner, ptrdiff_t curIndex)
1271 : iterator::indexed_accessor_iterator(owner, curIndex) {}
1272
1273
1274 friend indexed_accessor_range_base<DerivedT, BaseT, T, PointerT,
1275 ReferenceT>;
1276 };
1277
1278 indexed_accessor_range_base(iterator begin, iterator end)
1279 : base(offset_base(begin.getBase(), begin.getIndex())),
1280 count(end.getIndex() - begin.getIndex()) {}
1281 indexed_accessor_range_base(const iterator_range<iterator> &range)
1282 : indexed_accessor_range_base(range.begin(), range.end()) {}
1283 indexed_accessor_range_base(BaseT base, ptrdiff_t count)
1284 : base(base), count(count) {}
1285
1286 iterator begin() const { return iterator(base, 0); }
1287 iterator end() const { return iterator(base, count); }
1288 ReferenceT operator[](size_t Index) const {
1289 assert(Index < size() && "invalid index for value range");
1290 return DerivedT::dereference_iterator(base, static_cast<ptrdiff_t>(Index));
1291 }
1292 ReferenceT front() const {
1293 assert(!empty() && "expected non-empty range");
1294 return (*this)[0];
1295 }
1296 ReferenceT back() const {
1297 assert(!empty() && "expected non-empty range");
1298 return (*this)[size() - 1];
1299 }
1300
1301
1302 size_t size() const { return count; }
1303
1304
1305 bool empty() const { return size() == 0; }
1306
1307
1308 DerivedT slice(size_t n, size_t m) const {
1309 assert(n + m <= size() && "invalid size specifiers");
1310 return DerivedT(offset_base(base, n), m);
1311 }
1312
1313
1314 DerivedT drop_front(size_t n = 1) const {
1315 assert(size() >= n && "Dropping more elements than exist");
1316 return slice(n, size() - n);
1317 }
1318
1319 DerivedT drop_back(size_t n = 1) const {
1320 assert(size() >= n && "Dropping more elements than exist");
1321 return DerivedT(base, size() - n);
1322 }
1323
1324
1325 DerivedT take_front(size_t n = 1) const {
1326 return n < size() ? drop_back(size() - n)
1327 : static_cast<const DerivedT &>(*this);
1328 }
1329
1330
1331 DerivedT take_back(size_t n = 1) const {
1332 return n < size() ? drop_front(size() - n)
1333 : static_cast<const DerivedT &>(*this);
1334 }
1335
1336
1337 template <typename RangeT, typename = std::enable_if_t<std::is_constructible<
1338 RangeT, iterator_range<iterator>>::value>>
1339 operator RangeT() const {
1340 return RangeT(iterator_range<iterator>(*this));
1341 }
1342
1343
1344 const BaseT &getBase() const { return base; }
1345
1346 private:
1347
1348 static BaseT offset_base(const BaseT &base, size_t n) {
1349 return n == 0 ? base : DerivedT::offset_base(base, n);
1350 }
1351
1352 protected:
1353 indexed_accessor_range_base(const indexed_accessor_range_base &) = default;
1354 indexed_accessor_range_base(indexed_accessor_range_base &&) = default;
1355 indexed_accessor_range_base &
1356 operator=(const indexed_accessor_range_base &) = default;
1357
1358
1359 BaseT base;
1360
1361 ptrdiff_t count;
1362 };
1363
1364
1365 template <typename OtherT, typename DerivedT, typename BaseT, typename T,
1366 typename PointerT, typename ReferenceT>
1367 bool operator==(const indexed_accessor_range_base<DerivedT, BaseT, T, PointerT,
1368 ReferenceT> &lhs,
1369 const OtherT &rhs) {
1370 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
1371 }
1372
1373 template <typename OtherT, typename DerivedT, typename BaseT, typename T,
1374 typename PointerT, typename ReferenceT>
1375 bool operator!=(const indexed_accessor_range_base<DerivedT, BaseT, T, PointerT,
1376 ReferenceT> &lhs,
1377 const OtherT &rhs) {
1378 return !(lhs == rhs);
1379 }
1380 }
1381
1382
1383
1384
1385
1386
1387
1388
1389 template <typename DerivedT, typename BaseT, typename T,
1390 typename PointerT = T *, typename ReferenceT = T &>
1391 class indexed_accessor_range
1392 : public detail::indexed_accessor_range_base<
1393 DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT> {
1394 public:
1395 indexed_accessor_range(BaseT base, ptrdiff_t startIndex, ptrdiff_t count)
1396 : detail::indexed_accessor_range_base<
1397 DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT>(
1398 std::make_pair(base, startIndex), count) {}
1399 using detail::indexed_accessor_range_base<
1400 DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT,
1401 ReferenceT>::indexed_accessor_range_base;
1402
1403
1404 const BaseT &getBase() const { return this->base.first; }
1405
1406
1407 ptrdiff_t getStartIndex() const { return this->base.second; }
1408
1409
1410 static std::pair<BaseT, ptrdiff_t>
1411 offset_base(const std::pair<BaseT, ptrdiff_t> &base, ptrdiff_t index) {
1412
1413
1414 return std::make_pair(base.first, base.second + index);
1415 }
1416
1417 static ReferenceT
1418 dereference_iterator(const std::pair<BaseT, ptrdiff_t> &base,
1419 ptrdiff_t index) {
1420 return DerivedT::dereference(base.first, base.second + index);
1421 }
1422 };
1423
1424 namespace detail {
1425
1426
1427
1428
1429
1430
1431 template <typename EltTy, typename FirstTy> class first_or_second_type {
1432 public:
1433 using type = std::conditional_t<std::is_reference<EltTy>::value, FirstTy,
1434 std::remove_reference_t<FirstTy>>;
1435 };
1436 }
1437
1438
1439 template <typename ContainerTy> auto make_first_range(ContainerTy &&c) {
1440 using EltTy = decltype((*std::begin(c)));
1441 return llvm::map_range(std::forward<ContainerTy>(c),
1442 [](EltTy elt) -> typename detail::first_or_second_type<
1443 EltTy, decltype((elt.first))>::type {
1444 return elt.first;
1445 });
1446 }
1447
1448
1449 template <typename ContainerTy> auto make_second_range(ContainerTy &&c) {
1450 using EltTy = decltype((*std::begin(c)));
1451 return llvm::map_range(
1452 std::forward<ContainerTy>(c),
1453 [](EltTy elt) ->
1454 typename detail::first_or_second_type<EltTy,
1455 decltype((elt.second))>::type {
1456 return elt.second;
1457 });
1458 }
1459
1460
1461
1462
1463
1464
1465
1466
1467 struct less_first {
1468 template <typename T> bool operator()(const T &lhs, const T &rhs) const {
1469 return std::less<>()(std::get<0>(lhs), std::get<0>(rhs));
1470 }
1471 };
1472
1473
1474
1475
1476 struct less_second {
1477 template <typename T> bool operator()(const T &lhs, const T &rhs) const {
1478 return std::less<>()(std::get<1>(lhs), std::get<1>(rhs));
1479 }
1480 };
1481
1482
1483
1484 template<typename FuncTy>
1485 struct on_first {
1486 FuncTy func;
1487
1488 template <typename T>
1489 decltype(auto) operator()(const T &lhs, const T &rhs) const {
1490 return func(lhs.first, rhs.first);
1491 }
1492 };
1493
1494
1495
1496 template <int N> struct rank : rank<N - 1> {};
1497 template <> struct rank<0> {};
1498
1499 namespace detail {
1500 template <typename... Ts> struct Visitor;
1501
1502 template <typename HeadT, typename... TailTs>
1503 struct Visitor<HeadT, TailTs...> : remove_cvref_t<HeadT>, Visitor<TailTs...> {
1504 explicit constexpr Visitor(HeadT &&Head, TailTs &&...Tail)
1505 : remove_cvref_t<HeadT>(std::forward<HeadT>(Head)),
1506 Visitor<TailTs...>(std::forward<TailTs>(Tail)...) {}
1507 using remove_cvref_t<HeadT>::operator();
1508 using Visitor<TailTs...>::operator();
1509 };
1510
1511 template <typename HeadT> struct Visitor<HeadT> : remove_cvref_t<HeadT> {
1512 explicit constexpr Visitor(HeadT &&Head)
1513 : remove_cvref_t<HeadT>(std::forward<HeadT>(Head)) {}
1514 using remove_cvref_t<HeadT>::operator();
1515 };
1516 }
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546 template <typename... CallableTs>
1547 constexpr decltype(auto) makeVisitor(CallableTs &&...Callables) {
1548 return detail::Visitor<CallableTs...>(std::forward<CallableTs>(Callables)...);
1549 }
1550
1551
1552
1553
1554
1555
1556
1557 template <class Iterator, class RNG>
1558 void shuffle(Iterator first, Iterator last, RNG &&g) {
1559
1560
1561 typedef
1562 typename std::iterator_traits<Iterator>::difference_type difference_type;
1563 for (auto size = last - first; size > 1; ++first, (void)--size) {
1564 difference_type offset = g() % size;
1565
1566
1567 if (offset != difference_type(0))
1568 std::iter_swap(first, first + offset);
1569 }
1570 }
1571
1572
1573 template<typename T>
1574 inline int array_pod_sort_comparator(const void *P1, const void *P2) {
1575 if (std::less<T>()(*reinterpret_cast<const T*>(P1),
1576 *reinterpret_cast<const T*>(P2)))
1577 return -1;
1578 if (std::less<T>()(*reinterpret_cast<const T*>(P2),
1579 *reinterpret_cast<const T*>(P1)))
1580 return 1;
1581 return 0;
1582 }
1583
1584
1585
1586 template<typename T>
1587 inline int (*get_array_pod_sort_comparator(const T &))
1588 (const void*, const void*) {
1589 return array_pod_sort_comparator<T>;
1590 }
1591
1592 #ifdef EXPENSIVE_CHECKS
1593 namespace detail {
1594
1595 inline unsigned presortShuffleEntropy() {
1596 static unsigned Result(std::random_device{}());
1597 return Result;
1598 }
1599
1600 template <class IteratorTy>
1601 inline void presortShuffle(IteratorTy Start, IteratorTy End) {
1602 std::mt19937 Generator(presortShuffleEntropy());
1603 llvm::shuffle(Start, End, Generator);
1604 }
1605
1606 }
1607 #endif
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623 template<class IteratorTy>
1624 inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
1625
1626
1627 auto NElts = End - Start;
1628 if (NElts <= 1) return;
1629 #ifdef EXPENSIVE_CHECKS
1630 detail::presortShuffle<IteratorTy>(Start, End);
1631 #endif
1632 qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
1633 }
1634
1635 template <class IteratorTy>
1636 inline void array_pod_sort(
1637 IteratorTy Start, IteratorTy End,
1638 int (*Compare)(
1639 const typename std::iterator_traits<IteratorTy>::value_type *,
1640 const typename std::iterator_traits<IteratorTy>::value_type *)) {
1641
1642
1643 auto NElts = End - Start;
1644 if (NElts <= 1) return;
1645 #ifdef EXPENSIVE_CHECKS
1646 detail::presortShuffle<IteratorTy>(Start, End);
1647 #endif
1648 qsort(&*Start, NElts, sizeof(*Start),
1649 reinterpret_cast<int (*)(const void *, const void *)>(Compare));
1650 }
1651
1652 namespace detail {
1653 template <typename T>
1654
1655
1656 using sort_trivially_copyable = std::conjunction<
1657 std::is_pointer<T>,
1658 std::is_trivially_copyable<typename std::iterator_traits<T>::value_type>>;
1659 }
1660
1661
1662
1663 template <typename IteratorTy>
1664 inline void sort(IteratorTy Start, IteratorTy End) {
1665 if constexpr (detail::sort_trivially_copyable<IteratorTy>::value) {
1666
1667
1668 array_pod_sort(Start, End);
1669 } else {
1670 #ifdef EXPENSIVE_CHECKS
1671 detail::presortShuffle<IteratorTy>(Start, End);
1672 #endif
1673 std::sort(Start, End);
1674 }
1675 }
1676
1677 template <typename Container> inline void sort(Container &&C) {
1678 llvm::sort(adl_begin(C), adl_end(C));
1679 }
1680
1681 template <typename IteratorTy, typename Compare>
1682 inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
1683 #ifdef EXPENSIVE_CHECKS
1684 detail::presortShuffle<IteratorTy>(Start, End);
1685 #endif
1686 std::sort(Start, End, Comp);
1687 }
1688
1689 template <typename Container, typename Compare>
1690 inline void sort(Container &&C, Compare Comp) {
1691 llvm::sort(adl_begin(C), adl_end(C), Comp);
1692 }
1693
1694
1695
1696 template <typename R>
1697 auto size(R &&Range,
1698 std::enable_if_t<
1699 std::is_base_of<std::random_access_iterator_tag,
1700 typename std::iterator_traits<decltype(
1701 Range.begin())>::iterator_category>::value,
1702 void> * = nullptr) {
1703 return std::distance(Range.begin(), Range.end());
1704 }
1705
1706 namespace detail {
1707 template <typename Range>
1708 using check_has_free_function_size =
1709 decltype(adl_size(std::declval<Range &>()));
1710
1711 template <typename Range>
1712 static constexpr bool HasFreeFunctionSize =
1713 is_detected<check_has_free_function_size, Range>::value;
1714 }
1715
1716
1717
1718
1719
1720
1721
1722 template <typename R> constexpr size_t range_size(R &&Range) {
1723 if constexpr (detail::HasFreeFunctionSize<R>)
1724 return adl_size(Range);
1725 else
1726 return static_cast<size_t>(std::distance(adl_begin(Range), adl_end(Range)));
1727 }
1728
1729
1730
1731 template <typename R, typename UnaryFunction>
1732 UnaryFunction for_each(R &&Range, UnaryFunction F) {
1733 return std::for_each(adl_begin(Range), adl_end(Range), F);
1734 }
1735
1736
1737
1738 template <typename R, typename UnaryPredicate>
1739 bool all_of(R &&Range, UnaryPredicate P) {
1740 return std::all_of(adl_begin(Range), adl_end(Range), P);
1741 }
1742
1743
1744
1745 template <typename R, typename UnaryPredicate>
1746 bool any_of(R &&Range, UnaryPredicate P) {
1747 return std::any_of(adl_begin(Range), adl_end(Range), P);
1748 }
1749
1750
1751
1752 template <typename R, typename UnaryPredicate>
1753 bool none_of(R &&Range, UnaryPredicate P) {
1754 return std::none_of(adl_begin(Range), adl_end(Range), P);
1755 }
1756
1757
1758
1759 template <typename R, typename T> auto find(R &&Range, const T &Val) {
1760 return std::find(adl_begin(Range), adl_end(Range), Val);
1761 }
1762
1763
1764
1765 template <typename R, typename UnaryPredicate>
1766 auto find_if(R &&Range, UnaryPredicate P) {
1767 return std::find_if(adl_begin(Range), adl_end(Range), P);
1768 }
1769
1770 template <typename R, typename UnaryPredicate>
1771 auto find_if_not(R &&Range, UnaryPredicate P) {
1772 return std::find_if_not(adl_begin(Range), adl_end(Range), P);
1773 }
1774
1775
1776
1777 template <typename R, typename UnaryPredicate>
1778 auto remove_if(R &&Range, UnaryPredicate P) {
1779 return std::remove_if(adl_begin(Range), adl_end(Range), P);
1780 }
1781
1782
1783
1784 template <typename R, typename OutputIt, typename UnaryPredicate>
1785 OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) {
1786 return std::copy_if(adl_begin(Range), adl_end(Range), Out, P);
1787 }
1788
1789
1790
1791
1792
1793
1794 template <typename T, typename R, typename Predicate>
1795 T *find_singleton(R &&Range, Predicate P, bool AllowRepeats = false) {
1796 T *RC = nullptr;
1797 for (auto &&A : Range) {
1798 if (T *PRC = P(A, AllowRepeats)) {
1799 if (RC) {
1800 if (!AllowRepeats || PRC != RC)
1801 return nullptr;
1802 } else
1803 RC = PRC;
1804 }
1805 }
1806 return RC;
1807 }
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818 template <typename T, typename R, typename Predicate>
1819 std::pair<T *, bool> find_singleton_nested(R &&Range, Predicate P,
1820 bool AllowRepeats = false) {
1821 T *RC = nullptr;
1822 for (auto *A : Range) {
1823 std::pair<T *, bool> PRC = P(A, AllowRepeats);
1824 if (PRC.second) {
1825 assert(PRC.first == nullptr &&
1826 "Inconsistent return values in find_singleton_nested.");
1827 return PRC;
1828 }
1829 if (PRC.first) {
1830 if (RC) {
1831 if (!AllowRepeats || PRC.first != RC)
1832 return {nullptr, true};
1833 } else
1834 RC = PRC.first;
1835 }
1836 }
1837 return {RC, false};
1838 }
1839
1840 template <typename R, typename OutputIt>
1841 OutputIt copy(R &&Range, OutputIt Out) {
1842 return std::copy(adl_begin(Range), adl_end(Range), Out);
1843 }
1844
1845
1846
1847 template <typename R, typename OutputIt, typename UnaryPredicate, typename T>
1848 OutputIt replace_copy_if(R &&Range, OutputIt Out, UnaryPredicate P,
1849 const T &NewValue) {
1850 return std::replace_copy_if(adl_begin(Range), adl_end(Range), Out, P,
1851 NewValue);
1852 }
1853
1854
1855
1856 template <typename R, typename OutputIt, typename T>
1857 OutputIt replace_copy(R &&Range, OutputIt Out, const T &OldValue,
1858 const T &NewValue) {
1859 return std::replace_copy(adl_begin(Range), adl_end(Range), Out, OldValue,
1860 NewValue);
1861 }
1862
1863
1864
1865 template <typename R, typename T>
1866 void replace(R &&Range, const T &OldValue, const T &NewValue) {
1867 std::replace(adl_begin(Range), adl_end(Range), OldValue, NewValue);
1868 }
1869
1870
1871
1872 template <typename R, typename OutputIt>
1873 OutputIt move(R &&Range, OutputIt Out) {
1874 return std::move(adl_begin(Range), adl_end(Range), Out);
1875 }
1876
1877 namespace detail {
1878 template <typename Range, typename Element>
1879 using check_has_member_contains_t =
1880 decltype(std::declval<Range &>().contains(std::declval<const Element &>()));
1881
1882 template <typename Range, typename Element>
1883 static constexpr bool HasMemberContains =
1884 is_detected<check_has_member_contains_t, Range, Element>::value;
1885
1886 template <typename Range, typename Element>
1887 using check_has_member_find_t =
1888 decltype(std::declval<Range &>().find(std::declval<const Element &>()) !=
1889 std::declval<Range &>().end());
1890
1891 template <typename Range, typename Element>
1892 static constexpr bool HasMemberFind =
1893 is_detected<check_has_member_find_t, Range, Element>::value;
1894
1895 }
1896
1897
1898
1899
1900
1901
1902 template <typename R, typename E>
1903 bool is_contained(R &&Range, const E &Element) {
1904 if constexpr (detail::HasMemberContains<R, E>)
1905 return Range.contains(Element);
1906 else if constexpr (detail::HasMemberFind<R, E>)
1907 return Range.find(Element) != Range.end();
1908 else
1909 return std::find(adl_begin(Range), adl_end(Range), Element) !=
1910 adl_end(Range);
1911 }
1912
1913
1914
1915 template <typename T, typename E>
1916 constexpr bool is_contained(std::initializer_list<T> Set, const E &Element) {
1917
1918 for (const T &V : Set)
1919 if (V == Element)
1920 return true;
1921 return false;
1922 }
1923
1924
1925
1926 template <typename R, typename Compare> bool is_sorted(R &&Range, Compare C) {
1927 return std::is_sorted(adl_begin(Range), adl_end(Range), C);
1928 }
1929
1930
1931
1932 template <typename R> bool is_sorted(R &&Range) {
1933 return std::is_sorted(adl_begin(Range), adl_end(Range));
1934 }
1935
1936
1937
1938 template <typename R, typename E> auto count(R &&Range, const E &Element) {
1939 return std::count(adl_begin(Range), adl_end(Range), Element);
1940 }
1941
1942
1943
1944 template <typename R, typename UnaryPredicate>
1945 auto count_if(R &&Range, UnaryPredicate P) {
1946 return std::count_if(adl_begin(Range), adl_end(Range), P);
1947 }
1948
1949
1950
1951 template <typename R, typename OutputIt, typename UnaryFunction>
1952 OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F) {
1953 return std::transform(adl_begin(Range), adl_end(Range), d_first, F);
1954 }
1955
1956
1957
1958 template <typename R, typename UnaryPredicate>
1959 auto partition(R &&Range, UnaryPredicate P) {
1960 return std::partition(adl_begin(Range), adl_end(Range), P);
1961 }
1962
1963
1964
1965 template <typename R, typename T> auto binary_search(R &&Range, T &&Value) {
1966 return std::binary_search(adl_begin(Range), adl_end(Range),
1967 std::forward<T>(Value));
1968 }
1969
1970 template <typename R, typename T, typename Compare>
1971 auto binary_search(R &&Range, T &&Value, Compare C) {
1972 return std::binary_search(adl_begin(Range), adl_end(Range),
1973 std::forward<T>(Value), C);
1974 }
1975
1976
1977
1978 template <typename R, typename T> auto lower_bound(R &&Range, T &&Value) {
1979 return std::lower_bound(adl_begin(Range), adl_end(Range),
1980 std::forward<T>(Value));
1981 }
1982
1983 template <typename R, typename T, typename Compare>
1984 auto lower_bound(R &&Range, T &&Value, Compare C) {
1985 return std::lower_bound(adl_begin(Range), adl_end(Range),
1986 std::forward<T>(Value), C);
1987 }
1988
1989
1990
1991 template <typename R, typename T> auto upper_bound(R &&Range, T &&Value) {
1992 return std::upper_bound(adl_begin(Range), adl_end(Range),
1993 std::forward<T>(Value));
1994 }
1995
1996 template <typename R, typename T, typename Compare>
1997 auto upper_bound(R &&Range, T &&Value, Compare C) {
1998 return std::upper_bound(adl_begin(Range), adl_end(Range),
1999 std::forward<T>(Value), C);
2000 }
2001
2002
2003
2004 template <typename R> auto min_element(R &&Range) {
2005 return std::min_element(adl_begin(Range), adl_end(Range));
2006 }
2007
2008 template <typename R, typename Compare> auto min_element(R &&Range, Compare C) {
2009 return std::min_element(adl_begin(Range), adl_end(Range), C);
2010 }
2011
2012
2013
2014 template <typename R> auto max_element(R &&Range) {
2015 return std::max_element(adl_begin(Range), adl_end(Range));
2016 }
2017
2018 template <typename R, typename Compare> auto max_element(R &&Range, Compare C) {
2019 return std::max_element(adl_begin(Range), adl_end(Range), C);
2020 }
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031 template <typename R1, typename R2> auto mismatch(R1 &&Range1, R2 &&Range2) {
2032 return std::mismatch(adl_begin(Range1), adl_end(Range1), adl_begin(Range2),
2033 adl_end(Range2));
2034 }
2035
2036 template <typename R>
2037 void stable_sort(R &&Range) {
2038 std::stable_sort(adl_begin(Range), adl_end(Range));
2039 }
2040
2041 template <typename R, typename Compare>
2042 void stable_sort(R &&Range, Compare C) {
2043 std::stable_sort(adl_begin(Range), adl_end(Range), C);
2044 }
2045
2046
2047
2048 template <typename R, typename Predicate,
2049 typename Val = decltype(*adl_begin(std::declval<R>()))>
2050 auto partition_point(R &&Range, Predicate P) {
2051 return std::partition_point(adl_begin(Range), adl_end(Range), P);
2052 }
2053
2054 template<typename Range, typename Predicate>
2055 auto unique(Range &&R, Predicate P) {
2056 return std::unique(adl_begin(R), adl_end(R), P);
2057 }
2058
2059
2060
2061 template <typename Range> auto unique(Range &&R) {
2062 return std::unique(adl_begin(R), adl_end(R));
2063 }
2064
2065
2066
2067 template <typename L, typename R> bool equal(L &&LRange, R &&RRange) {
2068 return std::equal(adl_begin(LRange), adl_end(LRange), adl_begin(RRange),
2069 adl_end(RRange));
2070 }
2071
2072 template <typename L, typename R, typename BinaryPredicate>
2073 bool equal(L &&LRange, R &&RRange, BinaryPredicate P) {
2074 return std::equal(adl_begin(LRange), adl_end(LRange), adl_begin(RRange),
2075 adl_end(RRange), P);
2076 }
2077
2078
2079 template <typename R> bool all_equal(R &&Range) {
2080 auto Begin = adl_begin(Range);
2081 auto End = adl_end(Range);
2082 return Begin == End || std::equal(std::next(Begin), End, Begin);
2083 }
2084
2085
2086
2087 template <typename T> bool all_equal(std::initializer_list<T> Values) {
2088 return all_equal<std::initializer_list<T>>(std::move(Values));
2089 }
2090
2091
2092
2093
2094
2095
2096
2097
2098 template <typename Container, typename UnaryPredicate>
2099 void erase_if(Container &C, UnaryPredicate P) {
2100 C.erase(remove_if(C, P), C.end());
2101 }
2102
2103
2104
2105
2106 template <typename Container, typename ValueType>
2107 void erase(Container &C, ValueType V) {
2108 C.erase(std::remove(C.begin(), C.end(), V), C.end());
2109 }
2110
2111
2112
2113
2114 template <typename Container, typename Range>
2115 void append_range(Container &C, Range &&R) {
2116 C.insert(C.end(), adl_begin(R), adl_end(R));
2117 }
2118
2119
2120 template <typename Container, typename... Args>
2121 void append_values(Container &C, Args &&...Values) {
2122 C.reserve(range_size(C) + sizeof...(Args));
2123
2124 ((void)C.insert(C.end(), std::forward<Args>(Values)), ...);
2125 }
2126
2127
2128
2129 template<typename Container, typename RandomAccessIterator>
2130 void replace(Container &Cont, typename Container::iterator ContIt,
2131 typename Container::iterator ContEnd, RandomAccessIterator ValIt,
2132 RandomAccessIterator ValEnd) {
2133 while (true) {
2134 if (ValIt == ValEnd) {
2135 Cont.erase(ContIt, ContEnd);
2136 return;
2137 } else if (ContIt == ContEnd) {
2138 Cont.insert(ContIt, ValIt, ValEnd);
2139 return;
2140 }
2141 *ContIt++ = *ValIt++;
2142 }
2143 }
2144
2145
2146
2147 template<typename Container, typename Range = std::initializer_list<
2148 typename Container::value_type>>
2149 void replace(Container &Cont, typename Container::iterator ContIt,
2150 typename Container::iterator ContEnd, Range R) {
2151 replace(Cont, ContIt, ContEnd, R.begin(), R.end());
2152 }
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164 template <typename ForwardIterator, typename UnaryFunctor,
2165 typename NullaryFunctor,
2166 typename = std::enable_if_t<
2167 !std::is_constructible<StringRef, UnaryFunctor>::value &&
2168 !std::is_constructible<StringRef, NullaryFunctor>::value>>
2169 inline void interleave(ForwardIterator begin, ForwardIterator end,
2170 UnaryFunctor each_fn, NullaryFunctor between_fn) {
2171 if (begin == end)
2172 return;
2173 each_fn(*begin);
2174 ++begin;
2175 for (; begin != end; ++begin) {
2176 between_fn();
2177 each_fn(*begin);
2178 }
2179 }
2180
2181 template <typename Container, typename UnaryFunctor, typename NullaryFunctor,
2182 typename = std::enable_if_t<
2183 !std::is_constructible<StringRef, UnaryFunctor>::value &&
2184 !std::is_constructible<StringRef, NullaryFunctor>::value>>
2185 inline void interleave(const Container &c, UnaryFunctor each_fn,
2186 NullaryFunctor between_fn) {
2187 interleave(adl_begin(c), adl_end(c), each_fn, between_fn);
2188 }
2189
2190
2191 template <typename Container, typename UnaryFunctor, typename StreamT,
2192 typename T = detail::ValueOfRange<Container>>
2193 inline void interleave(const Container &c, StreamT &os, UnaryFunctor each_fn,
2194 const StringRef &separator) {
2195 interleave(adl_begin(c), adl_end(c), each_fn, [&] { os << separator; });
2196 }
2197 template <typename Container, typename StreamT,
2198 typename T = detail::ValueOfRange<Container>>
2199 inline void interleave(const Container &c, StreamT &os,
2200 const StringRef &separator) {
2201 interleave(
2202 c, os, [&](const T &a) { os << a; }, separator);
2203 }
2204
2205 template <typename Container, typename UnaryFunctor, typename StreamT,
2206 typename T = detail::ValueOfRange<Container>>
2207 inline void interleaveComma(const Container &c, StreamT &os,
2208 UnaryFunctor each_fn) {
2209 interleave(c, os, each_fn, ", ");
2210 }
2211 template <typename Container, typename StreamT,
2212 typename T = detail::ValueOfRange<Container>>
2213 inline void interleaveComma(const Container &c, StreamT &os) {
2214 interleaveComma(c, os, [&](const T &a) { os << a; });
2215 }
2216
2217
2218
2219
2220
2221 struct FreeDeleter {
2222 void operator()(void* v) {
2223 ::free(v);
2224 }
2225 };
2226
2227 template<typename First, typename Second>
2228 struct pair_hash {
2229 size_t operator()(const std::pair<First, Second> &P) const {
2230 return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second);
2231 }
2232 };
2233
2234
2235
2236 template <typename T> struct deref {
2237 T func;
2238
2239
2240
2241
2242 template <typename A, typename B> auto operator()(A &lhs, B &rhs) const {
2243 assert(lhs);
2244 assert(rhs);
2245 return func(*lhs, *rhs);
2246 }
2247 };
2248
2249 namespace detail {
2250
2251
2252 template <typename... Refs> struct enumerator_result;
2253
2254 template <typename... Iters>
2255 using EnumeratorTupleType = enumerator_result<decltype(*declval<Iters>())...>;
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268 template <typename... Iters>
2269 struct zip_enumerator : zip_common<zip_enumerator<Iters...>,
2270 EnumeratorTupleType<Iters...>, Iters...> {
2271 static_assert(sizeof...(Iters) >= 2, "Expected at least two iteratees");
2272 using zip_common<zip_enumerator<Iters...>, EnumeratorTupleType<Iters...>,
2273 Iters...>::zip_common;
2274
2275 bool operator==(const zip_enumerator &Other) const {
2276 return std::get<1>(this->iterators) == std::get<1>(Other.iterators);
2277 }
2278 };
2279
2280 template <typename... Refs> struct enumerator_result<std::size_t, Refs...> {
2281 static constexpr std::size_t NumRefs = sizeof...(Refs);
2282 static_assert(NumRefs != 0);
2283
2284 static constexpr std::size_t NumValues = NumRefs + 1;
2285
2286
2287 using range_reference_tuple = std::tuple<Refs...>;
2288
2289
2290 using value_reference_tuple = std::tuple<std::size_t, Refs...>;
2291
2292 enumerator_result(std::size_t Index, Refs &&...Rs)
2293 : Idx(Index), Storage(std::forward<Refs>(Rs)...) {}
2294
2295
2296
2297 std::size_t index() const { return Idx; }
2298
2299
2300
2301 decltype(auto) value() const {
2302 if constexpr (NumRefs == 1)
2303 return std::get<0>(Storage);
2304 else
2305 return Storage;
2306 }
2307
2308
2309 template <std::size_t I, typename = std::enable_if_t<I == 0>>
2310 friend std::size_t get(const enumerator_result &Result) {
2311 return Result.Idx;
2312 }
2313
2314
2315
2316 template <std::size_t I, typename = std::enable_if_t<I != 0>>
2317 friend decltype(auto) get(const enumerator_result &Result) {
2318
2319
2320
2321 return std::get<I - 1>(Result.Storage);
2322 }
2323
2324 template <typename... Ts>
2325 friend bool operator==(const enumerator_result &Result,
2326 const std::tuple<std::size_t, Ts...> &Other) {
2327 static_assert(NumRefs == sizeof...(Ts), "Size mismatch");
2328 if (Result.Idx != std::get<0>(Other))
2329 return false;
2330 return Result.is_value_equal(Other, std::make_index_sequence<NumRefs>{});
2331 }
2332
2333 private:
2334 template <typename Tuple, std::size_t... Idx>
2335 bool is_value_equal(const Tuple &Other, std::index_sequence<Idx...>) const {
2336 return ((std::get<Idx>(Storage) == std::get<Idx + 1>(Other)) && ...);
2337 }
2338
2339 std::size_t Idx;
2340
2341
2342
2343
2344
2345
2346
2347 mutable range_reference_tuple Storage;
2348 };
2349
2350 struct index_iterator
2351 : llvm::iterator_facade_base<index_iterator,
2352 std::random_access_iterator_tag, std::size_t> {
2353 index_iterator(std::size_t Index) : Index(Index) {}
2354
2355 index_iterator &operator+=(std::ptrdiff_t N) {
2356 Index += N;
2357 return *this;
2358 }
2359
2360 index_iterator &operator-=(std::ptrdiff_t N) {
2361 Index -= N;
2362 return *this;
2363 }
2364
2365 std::ptrdiff_t operator-(const index_iterator &R) const {
2366 return Index - R.Index;
2367 }
2368
2369
2370
2371
2372
2373
2374 std::size_t operator*() const { return Index; }
2375
2376 friend bool operator==(const index_iterator &Lhs, const index_iterator &Rhs) {
2377 return Lhs.Index == Rhs.Index;
2378 }
2379
2380 friend bool operator<(const index_iterator &Lhs, const index_iterator &Rhs) {
2381 return Lhs.Index < Rhs.Index;
2382 }
2383
2384 private:
2385 std::size_t Index;
2386 };
2387
2388
2389 struct index_stream {
2390 index_iterator begin() const { return {0}; }
2391 index_iterator end() const {
2392
2393
2394 return index_iterator{std::numeric_limits<std::size_t>::max()};
2395 }
2396 };
2397
2398 }
2399
2400
2401 class index_range {
2402 std::size_t Begin;
2403 std::size_t End;
2404
2405 public:
2406 index_range(std::size_t Begin, std::size_t End) : Begin(Begin), End(End) {}
2407 detail::index_iterator begin() const { return {Begin}; }
2408 detail::index_iterator end() const { return {End}; }
2409 };
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447 template <typename FirstRange, typename... RestRanges>
2448 auto enumerate(FirstRange &&First, RestRanges &&...Rest) {
2449 if constexpr (sizeof...(Rest) != 0) {
2450 #ifndef NDEBUG
2451
2452
2453 size_t sizes[] = {range_size(First), range_size(Rest)...};
2454 assert(all_equal(sizes) && "Ranges have different length");
2455 #endif
2456 }
2457 using enumerator = detail::zippy<detail::zip_enumerator, detail::index_stream,
2458 FirstRange, RestRanges...>;
2459 return enumerator(detail::index_stream{}, std::forward<FirstRange>(First),
2460 std::forward<RestRanges>(Rest)...);
2461 }
2462
2463 namespace detail {
2464
2465 template <typename Predicate, typename... Args>
2466 bool all_of_zip_predicate_first(Predicate &&P, Args &&...args) {
2467 auto z = zip(args...);
2468 auto it = z.begin();
2469 auto end = z.end();
2470 while (it != end) {
2471 if (!std::apply([&](auto &&...args) { return P(args...); }, *it))
2472 return false;
2473 ++it;
2474 }
2475 return it.all_equals(end);
2476 }
2477
2478
2479
2480 template <typename... ArgsThenPredicate, size_t... InputIndexes>
2481 bool all_of_zip_predicate_last(
2482 std::tuple<ArgsThenPredicate...> argsThenPredicate,
2483 std::index_sequence<InputIndexes...>) {
2484 auto constexpr OutputIndex =
2485 std::tuple_size<decltype(argsThenPredicate)>::value - 1;
2486 return all_of_zip_predicate_first(std::get<OutputIndex>(argsThenPredicate),
2487 std::get<InputIndexes>(argsThenPredicate)...);
2488 }
2489
2490 }
2491
2492
2493
2494
2495 template <typename... ArgsAndPredicate>
2496 bool all_of_zip(ArgsAndPredicate &&...argsAndPredicate) {
2497 return detail::all_of_zip_predicate_last(
2498 std::forward_as_tuple(argsAndPredicate...),
2499 std::make_index_sequence<sizeof...(argsAndPredicate) - 1>{});
2500 }
2501
2502
2503
2504
2505 template <typename IterTy,
2506 typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)>
2507 bool hasNItems(
2508 IterTy &&Begin, IterTy &&End, unsigned N,
2509 Pred &&ShouldBeCounted =
2510 [](const decltype(*std::declval<IterTy>()) &) { return true; },
2511 std::enable_if_t<
2512 !std::is_base_of<std::random_access_iterator_tag,
2513 typename std::iterator_traits<std::remove_reference_t<
2514 decltype(Begin)>>::iterator_category>::value,
2515 void> * = nullptr) {
2516 for (; N; ++Begin) {
2517 if (Begin == End)
2518 return false;
2519 N -= ShouldBeCounted(*Begin);
2520 }
2521 for (; Begin != End; ++Begin)
2522 if (ShouldBeCounted(*Begin))
2523 return false;
2524 return true;
2525 }
2526
2527
2528
2529
2530 template <typename IterTy,
2531 typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)>
2532 bool hasNItemsOrMore(
2533 IterTy &&Begin, IterTy &&End, unsigned N,
2534 Pred &&ShouldBeCounted =
2535 [](const decltype(*std::declval<IterTy>()) &) { return true; },
2536 std::enable_if_t<
2537 !std::is_base_of<std::random_access_iterator_tag,
2538 typename std::iterator_traits<std::remove_reference_t<
2539 decltype(Begin)>>::iterator_category>::value,
2540 void> * = nullptr) {
2541 for (; N; ++Begin) {
2542 if (Begin == End)
2543 return false;
2544 N -= ShouldBeCounted(*Begin);
2545 }
2546 return true;
2547 }
2548
2549
2550
2551 template <typename IterTy,
2552 typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)>
2553 bool hasNItemsOrLess(
2554 IterTy &&Begin, IterTy &&End, unsigned N,
2555 Pred &&ShouldBeCounted = [](const decltype(*std::declval<IterTy>()) &) {
2556 return true;
2557 }) {
2558 assert(N != std::numeric_limits<unsigned>::max());
2559 return !hasNItemsOrMore(Begin, End, N + 1, ShouldBeCounted);
2560 }
2561
2562
2563 template <typename ContainerTy> bool hasNItems(ContainerTy &&C, unsigned N) {
2564 return hasNItems(std::begin(C), std::end(C), N);
2565 }
2566
2567
2568 template <typename ContainerTy>
2569 bool hasNItemsOrMore(ContainerTy &&C, unsigned N) {
2570 return hasNItemsOrMore(std::begin(C), std::end(C), N);
2571 }
2572
2573
2574 template <typename ContainerTy>
2575 bool hasNItemsOrLess(ContainerTy &&C, unsigned N) {
2576 return hasNItemsOrLess(std::begin(C), std::end(C), N);
2577 }
2578
2579
2580
2581
2582
2583
2584
2585
2586 template <class Ptr> auto to_address(const Ptr &P) { return P.operator->(); }
2587 template <class T> constexpr T *to_address(T *P) { return P; }
2588
2589
2590 namespace detail {
2591 template <typename T> using has_sizeof = decltype(sizeof(T));
2592 }
2593
2594
2595
2596 template <typename T>
2597 constexpr bool is_incomplete_v = !is_detected<detail::has_sizeof, T>::value;
2598
2599 }
2600
2601 namespace std {
2602 template <typename... Refs>
2603 struct tuple_size<llvm::detail::enumerator_result<Refs...>>
2604 : std::integral_constant<std::size_t, sizeof...(Refs)> {};
2605
2606 template <std::size_t I, typename... Refs>
2607 struct tuple_element<I, llvm::detail::enumerator_result<Refs...>>
2608 : std::tuple_element<I, std::tuple<Refs...>> {};
2609
2610 template <std::size_t I, typename... Refs>
2611 struct tuple_element<I, const llvm::detail::enumerator_result<Refs...>>
2612 : std::tuple_element<I, std::tuple<Refs...>> {};
2613
2614 }
2615
2616 #endif