17#ifndef LLVM_ADT_STLEXTRAS_H
18#define LLVM_ADT_STLEXTRAS_H
25#include "llvm/Config/abi-breaking.h"
34#include <initializer_list>
44#ifdef EXPENSIVE_CHECKS
55 using type = std::add_pointer_t<std::add_const_t<T>>;
59 using type = std::add_lvalue_reference_t<std::add_const_t<T>>;
66template <typename T, bool isClass = std::is_class<T>::value>
70template <
typename ClassType,
typename ReturnType,
typename... Args>
79 template <
size_t Index>
80 using arg_t = std::tuple_element_t<Index, std::tuple<Args...>>;
83template <
typename ClassType,
typename ReturnType,
typename... Args>
87template <
typename ReturnType,
typename... Args>
97 using arg_t = std::tuple_element_t<i, std::tuple<Args...>>;
99template <
typename ReturnType,
typename... Args>
103template <
typename ReturnType,
typename... Args>
109template <
typename T,
typename... Ts>
110using is_one_of = std::disjunction<std::is_same<T, Ts>...>;
114template <
typename T,
typename... Ts>
119template <
typename T = void,
typename... Ts>
121template <
typename T = void,
typename... Ts>
133template <
typename T,
typename... Us>
135 : std::conjunction<std::negation<is_one_of<T, Us...>>,
136 TypesAreDistinct<Us...>> {};
149template <
typename T,
typename U,
typename... Us>
151 : std::integral_constant<size_t, 1 + FirstIndexOfType<T, Us...>::value> {};
152template <
typename T,
typename... Us>
158template <
size_t I,
typename... Ts>
163template <
typename EnumTy1,
typename EnumTy2,
164 typename = std::enable_if_t<std::is_enum_v<EnumTy1> &&
165 std::is_enum_v<EnumTy2>>>
187 bool = std::is_function_v<std::remove_pointer_t<remove_cvref_t<T>>>>
189 using value_type = std::remove_reference_t<T>;
190 using reference = value_type &;
191 using const_reference = value_type
const &;
193 std::optional<value_type> Obj;
195 static_assert(!std::is_pointer_v<value_type>,
196 "Pointers to non-functions are not callable.");
208 Obj.emplace(*
Other.Obj);
215 Obj.emplace(std::move(*
Other.Obj));
219 template <
typename... Pn,
220 std::enable_if_t<std::is_invocable_v<
T, Pn...>,
int> = 0>
221 decltype(
auto)
operator()(Pn &&...Params) {
222 return std::invoke(*Obj, std::forward<Pn>(Params)...);
225 template <
typename... Pn,
226 std::enable_if_t<std::is_invocable_v<
T const, Pn...>,
int> = 0>
227 decltype(
auto)
operator()(Pn &&...Params)
const {
228 return std::invoke(*Obj, std::forward<Pn>(Params)...);
231 bool valid()
const {
return Obj != std::nullopt; }
232 bool reset() {
return Obj = std::nullopt; }
234 operator reference() {
return *Obj; }
235 operator const_reference()
const {
return *Obj; }
241 static constexpr bool IsPtr = std::is_pointer_v<remove_cvref_t<T>>;
243 using StorageT = std::conditional_t<IsPtr, T, std::remove_reference_t<T> *>;
244 using CastT = std::conditional_t<IsPtr, T, T &>;
247 StorageT Func =
nullptr;
250 template <
typename In>
static constexpr auto convertIn(In &&
I) {
251 if constexpr (IsPtr) {
270 !std::is_same_v<remove_cvref_t<FnPtrOrRef>,
Callable>,
int
275 template <
typename... Pn,
276 std::enable_if_t<std::is_invocable_v<
T, Pn...>,
int> = 0>
278 return Func(std::forward<Pn>(Params)...);
281 bool valid()
const {
return Func !=
nullptr; }
284 operator T const &()
const {
285 if constexpr (IsPtr) {
289 static_assert(std::is_reference_v<T>,
290 "Expected a reference to a function.");
303 return B !=
E && std::next(
B) ==
E;
308template <
typename ContainerTy>
316template <
typename T>
auto drop_begin(
T &&RangeOrContainer,
size_t N = 1) {
323template <
typename T>
auto drop_end(
T &&RangeOrContainer,
size_t N = 1) {
325 std::prev(
adl_end(RangeOrContainer),
N));
331template <
typename ItTy,
typename FuncTy,
332 typename ReferenceTy =
333 std::invoke_result_t<FuncTy, decltype(*std::declval<ItTy>())>>
338 std::remove_reference_t<ReferenceTy>,
340 std::remove_reference_t<ReferenceTy> *, ReferenceTy> {
358template <
class ItTy,
class FuncTy>
365template <
class ContainerTy,
class FuncTy>
375template <
typename DerivedT,
typename ItTy,
typename ReferenceTy>
379 typename std::iterator_traits<ItTy>::iterator_category,
380 std::remove_reference_t<ReferenceTy>,
381 typename std::iterator_traits<ItTy>::difference_type,
382 std::remove_reference_t<ReferenceTy> *, ReferenceTy> {
392 return static_cast<const DerivedT &
>(*this).mapElement(*this->I);
397template <
typename Range>
399 decltype(
adl_rbegin(std::declval<Range &>()));
401template <
typename Range>
408template <
typename ContainerTy> [[nodiscard]]
auto reverse(ContainerTy &&
C) {
432template <
typename WrappedIteratorT,
typename PredicateT,
typename IterTag>
435 filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
437 std::common_type_t<IterTag,
438 typename std::iterator_traits<
439 WrappedIteratorT>::iterator_category>> {
447 while (this->I !=
End && !
Pred(*this->I))
463 using BaseT::operator++;
471 decltype(
auto)
operator*()
const {
472 assert(BaseT::wrapped() !=
End &&
"Cannot dereference end iterator!");
473 return BaseT::operator*();
476 decltype(
auto) operator->()
const {
477 assert(BaseT::wrapped() !=
End &&
"Cannot dereference end iterator!");
478 return BaseT::operator->();
484 typename IterTag = std::forward_iterator_tag>
496template <
typename WrappedIteratorT,
typename PredicateT>
498 std::bidirectional_iterator_tag>
500 std::bidirectional_iterator_tag> {
503 void findPrevValid() {
504 while (!this->
Pred(*this->I))
509 using BaseT::operator--;
528template <
typename IterT>
530 std::is_base_of_v<std::bidirectional_iterator_tag,
531 typename std::iterator_traits<IterT>::iterator_category>,
532 std::bidirectional_iterator_tag, std::forward_iterator_tag>;
538template <
typename WrappedIteratorT,
typename PredicateT>
550template <
typename RangeT,
typename PredicateT>
553 using FilterIteratorT =
557 return make_range(FilterIteratorT(
B,
E, Pred), FilterIteratorT(
E,
E, Pred));
571 "make_isa_range would return references into temporary elements");
592template <
typename WrappedIteratorT>
595 WrappedIteratorT, std::input_iterator_tag> {
598 using PointerT =
typename std::iterator_traits<WrappedIteratorT>::pointer;
601#if LLVM_ENABLE_ABI_BREAKING_CHECKS
602 bool IsEarlyIncremented =
false;
608 using BaseT::operator*;
609 decltype(*std::declval<WrappedIteratorT>())
operator*() {
610#if LLVM_ENABLE_ABI_BREAKING_CHECKS
611 assert(!IsEarlyIncremented &&
"Cannot dereference twice!");
612 IsEarlyIncremented =
true;
617 using BaseT::operator++;
619#if LLVM_ENABLE_ABI_BREAKING_CHECKS
620 assert(IsEarlyIncremented &&
"Cannot increment before dereferencing!");
621 IsEarlyIncremented =
false;
628#if LLVM_ENABLE_ABI_BREAKING_CHECKS
629 assert(!
LHS.IsEarlyIncremented &&
"Cannot compare after dereferencing!");
631 return (
const BaseT &)
LHS == (
const BaseT &)
RHS;
647template <
typename RangeT>
650 using EarlyIncIteratorT =
657template <
typename R,
typename UnaryPredicate>
658bool all_of(R &&range, UnaryPredicate
P);
660template <
typename R,
typename UnaryPredicate>
661bool any_of(R &&range, UnaryPredicate
P);
674 using type = std::tuple<decltype(*declval<Iters>())...>;
677template <
typename ZipType,
typename ReferenceTupleType,
typename... Iters>
681 std::bidirectional_iterator_tag,
682 typename std::iterator_traits<Iters>::iterator_category...>,
685 typename std::iterator_traits<
686 std::tuple_element_t<0, std::tuple<Iters...>>>::difference_type,
691 ReferenceTupleType *, ReferenceTupleType>;
693template <
typename ZipType,
typename ReferenceTupleType,
typename... Iters>
706 template <
size_t... Ns>
void tup_inc(std::index_sequence<Ns...>) {
710 template <
size_t... Ns>
void tup_dec(std::index_sequence<Ns...>) {
714 template <
size_t... Ns>
716 std::index_sequence<Ns...>)
const {
728 return static_cast<ZipType &
>(*this);
733 "All inner iterators must be at least bidirectional.");
735 return static_cast<ZipType &
>(*this);
744template <
typename... Iters>
746 typename ZipTupleType<Iters...>::type, Iters...> {
755template <
typename... Iters>
757 :
zip_common<zip_shortest<Iters...>, typename ZipTupleType<Iters...>::type,
763 return any_iterator_equals(other, std::index_sequence_for<Iters...>{});
767 template <
size_t... Ns>
769 std::index_sequence<Ns...>)
const {
776template <
template <
typename...>
class ItType,
typename TupleStorageType,
777 typename IndexSequence>
781template <
template <
typename...>
class ItType,
typename... Args,
784 std::index_sequence<Ns...>> {
786 std::get<Ns>(declval<std::tuple<Args...> &>())))...>;
790template <
template <
typename...>
class ItType,
typename... Args,
793 std::index_sequence<Ns...>> {
795 std::get<Ns>(declval<
const std::tuple<Args...> &>())))...>;
798template <
template <
typename...>
class ItType,
typename... Args>
class zippy {
800 std::tuple<Args...> storage;
801 using IndexSequence = std::index_sequence_for<Args...>;
805 IndexSequence>::type;
808 IndexSequence>::type;
824 template <
size_t... Ns>
828 template <
size_t... Ns>
iterator begin_impl(std::index_sequence<Ns...>) {
832 template <
size_t... Ns>
836 template <
size_t... Ns>
iterator end_impl(std::index_sequence<Ns...>) {
845template <
typename T,
typename U,
typename...
Args>
849 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(
args)...);
855template <
typename T,
typename U,
typename... Args>
859 "Iteratees do not have equal length");
861 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(
args)...);
868template <
typename T,
typename U,
typename... Args>
872 "First iteratee is not the shortest");
875 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(
args)...);
879template <
typename Iter>
886template <
typename Iter>
888 std::remove_const_t<std::remove_reference_t<
decltype(*I)>>> {
895 using type = std::optional<std::remove_const_t<
896 std::remove_reference_t<decltype(*std::declval<Iter>())>>>;
900 using type = std::tuple<typename ZipLongestItemType<Iters>::type...>;
903template <
typename... Iters>
906 zip_longest_iterator<Iters...>,
908 std::forward_iterator_tag,
909 typename std::iterator_traits<Iters>::iterator_category...>,
910 typename ZipLongestTupleType<Iters...>::type,
911 typename std::iterator_traits<
912 std::tuple_element_t<0, std::tuple<Iters...>>>::difference_type,
913 typename ZipLongestTupleType<Iters...>::type *,
914 typename ZipLongestTupleType<Iters...>::type> {
919 std::tuple<Iters...> iterators;
920 std::tuple<Iters...> end_iterators;
922 template <
size_t... Ns>
924 std::index_sequence<Ns...>)
const {
925 return ((std::get<Ns>(this->iterators) != std::get<Ns>(other.iterators)) ||
929 template <
size_t... Ns>
value_type deref(std::index_sequence<Ns...>)
const {
931 deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
934 template <
size_t... Ns>
935 decltype(iterators) tup_inc(std::index_sequence<Ns...>)
const {
936 return std::tuple<Iters...>(
937 next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
942 : iterators(
std::forward<Iters>(ts.first)...),
943 end_iterators(
std::forward<Iters>(ts.second)...) {}
946 return deref(std::index_sequence_for<Iters...>{});
950 iterators = tup_inc(std::index_sequence_for<Iters...>{});
955 return !
test(other, std::index_sequence_for<Iters...>{});
970 std::tuple<Args...> ts;
972 template <
size_t... Ns>
973 iterator begin_impl(std::index_sequence<Ns...>)
const {
975 adl_end(std::get<Ns>(ts)))...);
978 template <
size_t... Ns>
iterator end_impl(std::index_sequence<Ns...>)
const {
980 adl_end(std::get<Ns>(ts)))...);
987 return begin_impl(std::index_sequence_for<Args...>{});
989 iterator end()
const {
return end_impl(std::index_sequence_for<Args...>{}); }
996template <
typename T,
typename U,
typename... Args>
1000 std::forward<T>(t), std::forward<U>(u), std::forward<Args>(
args)...);
1013template <
typename ValueT,
typename... IterTs>
1016 std::forward_iterator_tag, ValueT> {
1017 using BaseT =
typename concat_iterator::iterator_facade_base;
1019 static constexpr bool ReturnsByValue =
1020 !(std::is_reference_v<decltype(*std::declval<IterTs>())> && ...);
1021 static constexpr bool ReturnsConvertibleType =
1023 std::remove_cv_t<ValueT>,
1025 (std::is_convertible_v<
decltype(*std::declval<IterTs>()), ValueT> && ...);
1029 using reference_type =
1030 std::conditional_t<ReturnsByValue || ReturnsConvertibleType, ValueT,
1039 std::tuple<IterTs...> Begins;
1040 std::tuple<IterTs...> Ends;
1044 template <
size_t Index,
size_t... Others>
void incrementImpl() {
1045 auto &Begin = std::get<Index>(Begins);
1046 auto &End = std::get<Index>(Ends);
1048 if constexpr (
sizeof...(Others) != 0)
1049 return incrementImpl<Others...>();
1058 template <
size_t... Ns>
void increment(std::index_sequence<Ns...>) {
1059 incrementImpl<Ns...>();
1064 template <
size_t Index,
size_t... Others> reference_type getImpl()
const {
1065 auto &Begin = std::get<Index>(Begins);
1066 auto &End = std::get<Index>(Ends);
1068 if constexpr (
sizeof...(Others) != 0)
1069 return getImpl<Others...>();
1071 "Attempted to get a pointer from an end concat iterator!");
1080 template <
size_t... Ns> reference_type get(std::index_sequence<Ns...>)
const {
1081 return getImpl<Ns...>();
1089 template <
typename... RangeTs>
1093 using BaseT::operator++;
1096 increment(std::index_sequence_for<IterTs...>());
1101 return get(std::index_sequence_for<IterTs...>());
1105 return Begins ==
RHS.Begins && Ends ==
RHS.Ends;
1120 decltype(
adl_begin(std::declval<RangeTs &>()))...>;
1123 std::tuple<RangeTs...> Ranges;
1125 template <
size_t... Ns>
iterator begin_impl(std::index_sequence<Ns...>) {
1126 return iterator(std::get<Ns>(Ranges)...);
1128 template <
size_t... Ns>
1129 iterator begin_impl(std::index_sequence<Ns...>)
const {
1130 return iterator(std::get<Ns>(Ranges)...);
1132 template <
size_t... Ns>
iterator end_impl(std::index_sequence<Ns...>) {
1134 adl_end(std::get<Ns>(Ranges)))...);
1136 template <
size_t... Ns> iterator end_impl(std::index_sequence<Ns...>)
const {
1138 adl_end(std::get<Ns>(Ranges)))...);
1143 : Ranges(
std::forward<RangeTs>(Ranges)...) {}
1146 return begin_impl(std::index_sequence_for<RangeTs...>{});
1149 return begin_impl(std::index_sequence_for<RangeTs...>{});
1152 return end_impl(std::index_sequence_for<RangeTs...>{});
1155 return end_impl(std::index_sequence_for<RangeTs...>{});
1165template <
typename ValueT,
typename... RangeTs>
1166[[nodiscard]] detail::concat_range<ValueT, RangeTs...>
1168 static_assert(
sizeof...(RangeTs) > 1,
1169 "Need more than one range to concatenate!");
1171 std::forward<RangeTs>(Ranges)...);
1176template <
typename DerivedT,
typename BaseT,
typename T,
1177 typename PointerT =
T *,
typename ReferenceT =
T &>
1180 std::random_access_iterator_tag, T,
1181 std::ptrdiff_t, PointerT, ReferenceT> {
1197 this->
index += offset;
1198 return static_cast<DerivedT &
>(*this);
1201 this->
index -= offset;
1202 return static_cast<DerivedT &
>(*this);
1229template <
typename DerivedT,
typename BaseT,
typename T,
1230 typename PointerT =
T *,
typename ReferenceT =
T &>
1237 PointerT, ReferenceT> {
1242 return DerivedT::dereference_iterator(this->
getBase(), this->
getIndex());
1265 assert(Index <
size() &&
"invalid index for value range");
1266 return DerivedT::dereference_iterator(
base,
static_cast<ptrdiff_t>(Index));
1274 return (*
this)[
size() - 1];
1284 DerivedT
slice(
size_t n,
size_t m)
const {
1285 assert(n + m <=
size() &&
"invalid size specifiers");
1286 return DerivedT(offset_base(
base, n), m);
1291 assert(
size() >= n &&
"Dropping more elements than exist");
1296 assert(
size() >= n &&
"Dropping more elements than exist");
1303 :
static_cast<const DerivedT &
>(*this);
1309 :
static_cast<const DerivedT &
>(*this);
1313 template <
typename RangeT,
typename = std::enable_if_t<std::is_constructible<
1315 operator RangeT()
const {
1324 static BaseT offset_base(
const BaseT &
base,
size_t n) {
1325 return n == 0 ?
base : DerivedT::offset_base(
base, n);
1341template <
typename OtherT,
typename DerivedT,
typename BaseT,
typename T,
1342 typename PointerT,
typename ReferenceT>
1345 const OtherT &rhs) {
1346 return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
1349template <
typename OtherT,
typename DerivedT,
typename BaseT,
typename T,
1350 typename PointerT,
typename ReferenceT>
1353 const OtherT &rhs) {
1354 return !(lhs == rhs);
1365template <
typename DerivedT,
typename BaseT,
typename T,
1366 typename PointerT =
T *,
typename ReferenceT =
T &>
1369 DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT> {
1373 DerivedT,
std::pair<BaseT,
ptrdiff_t>,
T, PointerT, ReferenceT>(
1376 DerivedT, std::pair<BaseT, ptrdiff_t>,
T, PointerT,
1386 static std::pair<BaseT, ptrdiff_t>
1390 return {
base.first,
base.second + index};
1396 return DerivedT::dereference(
base.first,
base.second + index);
1409 using type = std::conditional_t<std::is_reference<EltTy>::value, FirstTy,
1410 std::remove_reference_t<FirstTy>>;
1419 EltTy,
decltype((elt.first))>::type {
1428 std::forward<ContainerTy>(c),
1431 decltype((elt.second))>::type {
1438template <
typename ContainerTy>
1441 using ReferenceTy =
typename std::iterator_traits<IterTy>::reference;
1443 [ShouldReverse](
auto I) -> ReferenceTy {
1444 return ShouldReverse ? std::get<0>(
I) : std::get<1>(
I);
1457 return std::less<>()(std::get<0>(lhs), std::get<0>(rhs));
1466 return std::less<>()(std::get<1>(lhs), std::get<1>(rhs));
1472template<
typename FuncTy>
1476 template <
typename T>
1477 decltype(
auto)
operator()(
const T &lhs,
const T &rhs)
const {
1478 return func(lhs.first, rhs.first);
1490template <
typename HeadT,
typename... TailTs>
1492 explicit constexpr Visitor(HeadT &&Head, TailTs &&...Tail)
1494 Visitor<TailTs...>(
std::forward<TailTs>(Tail)...) {}
1496 using Visitor<TailTs...>::operator();
1534template <
typename... CallableTs>
1536 return detail::Visitor<CallableTs...>(std::forward<CallableTs>(Callables)...);
1545template <
class Iterator,
class RNG>
1549 using difference_type =
1550 typename std::iterator_traits<Iterator>::difference_type;
1551 for (
auto size = last - first;
size > 1; ++first, (void)--
size) {
1552 difference_type offset =
g() %
size;
1555 if (offset != difference_type(0))
1556 std::iter_swap(first, first + offset);
1563 if (std::less<T>()(*
reinterpret_cast<const T*
>(P1),
1564 *
reinterpret_cast<const T*
>(P2)))
1566 if (std::less<T>()(*
reinterpret_cast<const T*
>(P2),
1567 *
reinterpret_cast<const T*
>(P1)))
1576 (
const void*,
const void*) {
1580#ifdef EXPENSIVE_CHECKS
1583inline unsigned presortShuffleEntropy() {
1584 static unsigned Result(std::random_device{}());
1588template <
class IteratorTy>
1589inline void presortShuffle(IteratorTy Start, IteratorTy End) {
1590 std::mt19937 Generator(presortShuffleEntropy());
1611template<
class IteratorTy>
1615 auto NElts = End - Start;
1616 if (NElts <= 1)
return;
1617#ifdef EXPENSIVE_CHECKS
1618 detail::presortShuffle<IteratorTy>(Start, End);
1623template <
class IteratorTy>
1625 IteratorTy Start, IteratorTy End,
1627 const typename std::iterator_traits<IteratorTy>::value_type *,
1628 const typename std::iterator_traits<IteratorTy>::value_type *)) {
1631 auto NElts = End - Start;
1632 if (NElts <= 1)
return;
1633#ifdef EXPENSIVE_CHECKS
1634 detail::presortShuffle<IteratorTy>(Start, End);
1636 qsort(&*Start, NElts,
sizeof(*Start),
1637 reinterpret_cast<int (*)(
const void *,
const void *)
>(Compare));
1641template <
typename T>
1646 std::is_trivially_copyable<typename std::iterator_traits<T>::value_type>>;
1651template <
typename IteratorTy>
1652inline void sort(IteratorTy Start, IteratorTy End) {
1658#ifdef EXPENSIVE_CHECKS
1659 detail::presortShuffle<IteratorTy>(Start, End);
1661 std::sort(Start, End);
1665template <
typename Container>
inline void sort(Container &&
C) {
1669template <
typename IteratorTy,
typename Compare>
1670inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
1671#ifdef EXPENSIVE_CHECKS
1672 detail::presortShuffle<IteratorTy>(Start, End);
1674 std::sort(Start, End, Comp);
1677template <
typename Container,
typename Compare>
1678inline void sort(Container &&
C, Compare Comp) {
1684template <
typename R>
1687 std::is_base_of<std::random_access_iterator_tag,
1688 typename std::iterator_traits<
decltype(
1689 Range.begin())>::iterator_category>::value,
1690 void> * =
nullptr) {
1691 return std::distance(
Range.begin(),
Range.end());
1695template <
typename Range>
1697 decltype(
adl_size(std::declval<Range &>()));
1699template <
typename Range>
1720 std::forward<E>(
Init));
1724template <
typename R,
typename E,
typename BinaryOp>
1727 std::forward<E>(
Init), std::forward<BinaryOp>(
Op));
1732template <
typename R,
typename E = detail::ValueOfRange<R>>
1739template <
typename R,
typename E = detail::ValueOfRange<R>>
1742 std::multiplies<>{});
1747template <
typename R,
typename UnaryFunction>
1754template <
typename R,
typename UnaryPredicate>
1761template <
typename R,
typename UnaryPredicate>
1768template <
typename R,
typename UnaryPredicate>
1781template <
typename R,
typename T>
auto find(R &&
Range,
const T &Val) {
1787template <
typename R,
typename UnaryPredicate>
1792template <
typename R,
typename UnaryPredicate>
1799template <
typename R,
typename UnaryPredicate>
1806template <
typename R,
typename OutputIt,
typename UnaryPredicate>
1815template <
typename R1,
typename R2>
auto search(R1 &&Range1,
R2 &&Range2) {
1824template <
typename R1,
typename R2,
typename BinaryPredicate>
1842template <
typename R,
typename BinaryPredicate>
1852template <
typename T,
typename R,
typename Predicate>
1856 if (
T *PRC =
P(
A, AllowRepeats)) {
1858 if (!AllowRepeats || PRC != RC)
1877template <
typename T,
typename R,
typename Predicate>
1879 bool AllowRepeats =
false) {
1882 std::pair<T *, bool> PRC =
P(
A, AllowRepeats);
1884 assert(PRC.first ==
nullptr &&
1885 "Inconsistent return values in find_singleton_nested.");
1890 if (!AllowRepeats || PRC.first != RC)
1891 return {
nullptr,
true};
1900template <
typename R,
typename OutputIt>
1907template <
typename R,
typename OutputIt,
typename UnaryPredicate,
typename T>
1909 const T &NewValue) {
1916template <
typename R,
typename OutputIt,
typename T>
1918 const T &NewValue) {
1925template <
typename R,
typename T>
1932template <
typename R,
typename OutputIt>
1938template <
typename Range,
typename Element>
1940 decltype(std::declval<Range &>().contains(std::declval<const Element &>()));
1942template <
typename Range,
typename Element>
1946template <
typename Range,
typename Element>
1948 decltype(std::declval<Range &>().find(std::declval<const Element &>()) !=
1949 std::declval<Range &>().end());
1951template <
typename Range,
typename Element>
1962template <
typename R,
typename E>
1965 return Range.contains(Element);
1975template <
typename T,
typename E>
1978 for (
const T &V : Set)
1999template <
typename R,
typename Cmp = std::less<>>
2008template <
typename R1,
typename R2>
bool includes(R1 &&Range1,
R2 &&Range2) {
2009 assert(
is_sorted(Range1) &&
"Range1 must be sorted in non-descending order");
2010 assert(
is_sorted(Range2) &&
"Range2 must be sorted in non-descending order");
2018template <
typename R1,
typename R2,
typename Compare>
2023 adl_end(Range2), std::forward<Compare>(
C));
2028template <
typename R,
typename E>
auto count(R &&
Range,
const E &Element) {
2034template <
typename R,
typename UnaryPredicate>
2041template <
typename R,
typename OutputIt,
typename UnaryFunction>
2048template <
typename R,
typename UnaryPredicate>
2057 std::forward<T>(
Value));
2060template <
typename R,
typename T,
typename Compare>
2063 std::forward<T>(
Value),
C);
2070 std::forward<T>(
Value));
2073template <
typename R,
typename T,
typename Compare>
2076 std::forward<T>(
Value),
C);
2083 std::forward<T>(
Value));
2086template <
typename R,
typename T,
typename Compare>
2089 std::forward<T>(
Value),
C);
2121template <
typename R1,
typename R2>
auto mismatch(R1 &&Range1,
R2 &&Range2) {
2126template <
typename R,
typename IterTy>
2131template <
typename R>
2136template <
typename R,
typename Compare>
2143template <
typename R,
typename Predicate,
2144 typename Val =
decltype(*
adl_begin(std::declval<R>()))>
2149template<
typename Range,
typename Predicate>
2162template <
typename L,
typename R>
bool equal(L &&LRange, R &&RRange) {
2167template <
typename L,
typename R,
typename BinaryPredicate>
2168bool equal(L &&LRange, R &&RRange, BinaryPredicate
P) {
2177 return Begin == End || std::equal(std::next(Begin), End, Begin);
2207template <
typename Container,
typename UnaryPredicate>
2215template <
typename Container,
typename ValueType>
2217 C.erase(std::remove(
C.begin(),
C.end(), V),
C.end());
2223template <
typename Container,
typename Range>
2229template <
typename Container,
typename... Args>
2231 if (
size_t InitialSize =
range_size(
C); InitialSize == 0) {
2240 C.reserve(InitialSize +
sizeof...(Args));
2243 ((void)
C.insert(
C.end(), std::forward<Args>(
Values)), ...);
2248template <
typename Container,
typename RandomAccessIterator>
2249void replace(Container &Cont,
typename Container::iterator ContIt,
2250 typename Container::iterator ContEnd, RandomAccessIterator ValIt,
2251 RandomAccessIterator ValEnd) {
2253 if (ValIt == ValEnd) {
2254 Cont.erase(ContIt, ContEnd);
2257 if (ContIt == ContEnd) {
2258 Cont.insert(ContIt, ValIt, ValEnd);
2269template <
typename Container,
typename Range = std::initializer_list<
2270 typename Container::value_type>>
2271void replace(Container &Cont,
typename Container::iterator ContIt,
2272 typename Container::iterator ContEnd,
Range &&R) {
2286template <
typename ForwardIterator,
typename UnaryFunctor,
2287 typename NullaryFunctor,
2288 typename = std::enable_if_t<
2289 !std::is_constructible<StringRef, UnaryFunctor>::value &&
2290 !std::is_constructible<StringRef, NullaryFunctor>::value>>
2291inline void interleave(ForwardIterator begin, ForwardIterator end,
2292 UnaryFunctor each_fn, NullaryFunctor between_fn) {
2297 for (; begin != end; ++begin) {
2303template <
typename Container,
typename UnaryFunctor,
typename NullaryFunctor,
2304 typename = std::enable_if_t<
2305 !std::is_constructible<StringRef, UnaryFunctor>::value &&
2306 !std::is_constructible<StringRef, NullaryFunctor>::value>>
2308 NullaryFunctor between_fn) {
2313template <
typename Container,
typename UnaryFunctor,
typename StreamT,
2315inline void interleave(
const Container &c, StreamT &os, UnaryFunctor each_fn,
2319template <
typename Container,
typename StreamT,
2324 c, os, [&](
const T &a) { os << a; }, separator);
2327template <
typename Container,
typename UnaryFunctor,
typename StreamT,
2330 UnaryFunctor each_fn) {
2333template <
typename Container,
typename StreamT,
2349template<
typename First,
typename Second>
2352 return std::hash<First>()(
P.first) * 31 + std::hash<Second>()(
P.second);
2367 return func(*lhs, *rhs);
2376template <
typename... Iters>
2390template <
typename... Iters>
2392 EnumeratorTupleType<Iters...>, Iters...> {
2393 static_assert(
sizeof...(Iters) >= 2,
"Expected at least two iteratees");
2398 return std::get<1>(this->
iterators) == std::get<1>(
Other.iterators);
2403 static constexpr std::size_t
NumRefs =
sizeof...(Refs);
2415 : Idx(Index), Storage(
std::forward<Refs>(Rs)...) {}
2419 std::size_t
index()
const {
return Idx; }
2425 return std::get<0>(Storage);
2431 template <std::
size_t I,
typename = std::enable_if_t<I == 0>>
2438 template <std::
size_t I,
typename = std::enable_if_t<I != 0>>
2443 return std::get<
I - 1>(Result.Storage);
2446 template <
typename... Ts>
2448 const std::tuple<std::size_t, Ts...> &
Other) {
2449 static_assert(
NumRefs ==
sizeof...(Ts),
"Size mismatch");
2450 if (Result.Idx != std::get<0>(
Other))
2452 return Result.is_value_equal(
Other, std::make_index_sequence<NumRefs>{});
2456 template <
typename Tuple, std::size_t... Idx>
2457 bool is_value_equal(
const Tuple &
Other, std::index_sequence<Idx...>)
const {
2458 return ((std::get<Idx>(Storage) == std::get<Idx + 1>(
Other)) && ...);
2469 mutable range_reference_tuple Storage;
2474 std::random_access_iterator_tag, std::size_t> {
2488 return Index - R.Index;
2499 return Lhs.Index == Rhs.Index;
2503 return Lhs.Index < Rhs.Index;
2528 index_range(std::size_t Begin, std::size_t End) : Begin(Begin), End(End) {}
2569template <
typename FirstRange,
typename... RestRanges>
2571 if constexpr (
sizeof...(Rest) != 0) {
2580 FirstRange, RestRanges...>;
2582 std::forward<RestRanges>(Rest)...);
2587template <
typename Predicate,
typename... Args>
2590 auto it = z.begin();
2593 if (!std::apply([&](
auto &&...
args) {
return P(
args...); }, *it))
2597 return it.all_equals(end);
2602template <
typename... ArgsThenPredicate,
size_t... InputIndexes>
2604 std::tuple<ArgsThenPredicate...> argsThenPredicate,
2605 std::index_sequence<InputIndexes...>) {
2606 auto constexpr OutputIndex =
2607 std::tuple_size<
decltype(argsThenPredicate)>
::value - 1;
2609 std::get<InputIndexes>(argsThenPredicate)...);
2617template <
typename... ArgsAndPredicate>
2620 std::forward_as_tuple(argsAndPredicate...),
2621 std::make_index_sequence<
sizeof...(argsAndPredicate) - 1>{});
2627template <
typename IterTy,
2628 typename Pred =
bool (*)(
const decltype(*std::declval<IterTy>()) &)>
2630 IterTy &&Begin, IterTy &&End,
unsigned N,
2631 Pred &&ShouldBeCounted =
2632 [](
const decltype(*std::declval<IterTy>()) &) {
return true; },
2634 !std::is_base_of<std::random_access_iterator_tag,
2635 typename std::iterator_traits<std::remove_reference_t<
2636 decltype(Begin)>>::iterator_category>::value,
2637 void> * =
nullptr) {
2638 for (;
N; ++Begin) {
2641 N -= ShouldBeCounted(*Begin);
2643 for (; Begin != End; ++Begin)
2644 if (ShouldBeCounted(*Begin))
2652template <
typename IterTy,
2653 typename Pred = bool (*)(
const decltype(*std::declval<IterTy>()) &)>
2655 IterTy &&Begin, IterTy &&End,
unsigned N,
2656 Pred &&ShouldBeCounted =
2657 [](
const decltype(*std::declval<IterTy>()) &) {
return true; },
2659 !std::is_base_of<std::random_access_iterator_tag,
2660 typename std::iterator_traits<std::remove_reference_t<
2661 decltype(Begin)>>::iterator_category>::value,
2662 void> * =
nullptr) {
2663 for (;
N; ++Begin) {
2666 N -= ShouldBeCounted(*Begin);
2673template <
typename IterTy,
2674 typename Pred = bool (*)(
const decltype(*std::declval<IterTy>()) &)>
2676 IterTy &&Begin, IterTy &&End,
unsigned N,
2677 Pred &&ShouldBeCounted = [](
const decltype(*std::declval<IterTy>()) &) {
2680 assert(
N != std::numeric_limits<unsigned>::max());
2685template <
typename ContainerTy>
bool hasNItems(ContainerTy &&
C,
unsigned N) {
2690template <
typename ContainerTy>
2696template <
typename ContainerTy>
2708template <
typename T>
2713template <
typename T,
typename U>
2715 decltype(std::declval<const T &>() == std::declval<const U &>());
2719template <
typename T,
typename U = T>
2725template <
typename... Refs>
2726struct tuple_size<
llvm::detail::enumerator_result<Refs...>>
2727 : std::integral_constant<std::size_t, sizeof...(Refs)> {};
2729template <std::size_t
I,
typename... Refs>
2730struct tuple_element<
I,
llvm::detail::enumerator_result<Refs...>>
2731 : std::tuple_element<I, std::tuple<Refs...>> {};
2733template <std::size_t
I,
typename... Refs>
2734struct tuple_element<
I,
const llvm::detail::enumerator_result<Refs...>>
2735 : std::tuple_element<I, std::tuple<Refs...>> {};
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
This file contains library features backported from future STL versions.
INLINE void g(uint32_t *state, size_t a, size_t b, size_t c, size_t d, uint32_t x, uint32_t y)
Represent a constant reference to a string, i.e.
LLVM Value Representation.
decltype(auto) operator()(Pn &&...Params) const
Templated storage wrapper for a callable.
Callable & operator=(Callable &&Other)
Callable(Callable const &Other)=default
Callable & operator=(Callable const &Other)
Callable(Callable &&Other)=default
Iterator wrapper that concatenates sequences together.
concat_iterator & operator++()
bool operator==(const concat_iterator &RHS) const
reference_type operator*() const
concat_iterator(RangeTs &&...Ranges)
Constructs an iterator from a sequence of ranges.
Helper to store a sequence of ranges being concatenated and access them.
concat_range(RangeTs &&... Ranges)
concat_iterator< ValueT, decltype(adl_begin(std::declval< RangeTs & >()))... > iterator
Return a reference to the first or second member of a reference.
std::conditional_t< std::is_reference< EltTy >::value, FirstTy, std::remove_reference_t< FirstTy > > type
An iterator element of this range.
ReferenceT operator*() const
The class represents the base of a range of indexed_accessor_iterators.
DerivedT slice(size_t n, size_t m) const
Drop the first N elements, and keep M elements.
size_t size() const
Return the size of this range.
bool empty() const
Return if the range is empty.
indexed_accessor_range_base & operator=(const indexed_accessor_range_base &)=default
DerivedT take_front(size_t n=1) const
Take the first n elements.
ReferenceT operator[](size_t Index) const
DerivedT drop_back(size_t n=1) const
Drop the last n elements.
indexed_accessor_range_base RangeBaseT
DerivedT take_back(size_t n=1) const
Take the last n elements.
DerivedT drop_front(size_t n=1) const
Drop the first n elements.
indexed_accessor_range_base(const indexed_accessor_range_base &)=default
indexed_accessor_range_base(BaseT base, ptrdiff_t count)
indexed_accessor_range_base(indexed_accessor_range_base &&)=default
indexed_accessor_range_base(iterator begin, iterator end)
ptrdiff_t count
The size from the owning range.
BaseT base
The base that owns the provided range of values.
indexed_accessor_range_base(const iterator_range< iterator > &range)
const BaseT & getBase() const
Returns the base of this range.
zip_longest_iterator(std::pair< Iters &&, Iters && >... ts)
value_type operator*() const
bool operator==(const zip_longest_iterator< Iters... > &other) const
zip_longest_iterator< Iters... > & operator++()
typename ZipLongestTupleType< Iters... >::type value_type
typename iterator::iterator_category iterator_category
typename iterator::pointer pointer
typename iterator::difference_type difference_type
zip_longest_iterator< decltype(adl_begin(std::declval< Args >()))... > iterator
typename iterator::reference reference
zip_longest_range(Args &&... ts_)
typename iterator::value_type value_type
typename ZippyIteratorTuple< ItType, decltype(storage), IndexSequence >::type iterator
typename iterator::value_type value_type
typename iterator::difference_type difference_type
typename iterator::reference reference
typename iterator::pointer pointer
typename ZippyIteratorTuple< ItType, const decltype(storage), IndexSequence >::type const_iterator
typename const_iterator::reference const_reference
const_iterator begin() const
typename iterator::iterator_category iterator_category
const_iterator end() const
A pseudo-iterator adaptor that is designed to implement "early increment" style loops.
friend bool operator==(const early_inc_iterator_impl &LHS, const early_inc_iterator_impl &RHS)
early_inc_iterator_impl(WrappedIteratorT I)
early_inc_iterator_impl & operator++()
decltype(*std::declval< WrappedIteratorT >()) operator*()
An iterator adaptor that filters the elements of given inner iterators.
filter_iterator_base & operator++()
filter_iterator_base()=default
filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred)
filter_iterator_impl()=default
filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred)
filter_iterator_impl & operator--()
Specialization of filter_iterator_base for forward iteration only.
filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End, PredicateT Pred)
filter_iterator_impl()=default
index_range(std::size_t Begin, std::size_t End)
detail::index_iterator begin() const
detail::index_iterator end() const
A utility class used to implement an iterator that contains some base object and an index.
DerivedT & operator+=(ptrdiff_t offset)
const BaseT & getBase() const
Returns the current base of the iterator.
bool operator==(const indexed_accessor_iterator &rhs) const
indexed_accessor_iterator(BaseT base, ptrdiff_t index)
DerivedT & operator-=(ptrdiff_t offset)
ptrdiff_t operator-(const indexed_accessor_iterator &rhs) const
bool operator<(const indexed_accessor_iterator &rhs) const
ptrdiff_t getIndex() const
Returns the current index of the iterator.
indexed_accessor_range(BaseT base, ptrdiff_t startIndex, ptrdiff_t count)
const BaseT & getBase() const
Returns the current base of the range.
ptrdiff_t getStartIndex() const
Returns the current start index of the range.
static ReferenceT dereference_iterator(const std::pair< BaseT, ptrdiff_t > &base, ptrdiff_t index)
See detail::indexed_accessor_range_base for details.
static std::pair< BaseT, ptrdiff_t > offset_base(const std::pair< BaseT, ptrdiff_t > &base, ptrdiff_t index)
See detail::indexed_accessor_range_base for details.
iterator_adaptor_base()=default
DifferenceTypeT difference_type
CRTP base class which implements the entire standard iterator facade in terms of a minimal subset of ...
IteratorCategoryT iterator_category
std::iterator_traits< std::tuple_element_t< 0, std::tuple< Iters... > > >::difference_type difference_type
ZipLongestTupleType< Iters... >::type reference
ZipLongestTupleType< Iters... >::type * pointer
A range adaptor for a pair of iterators.
mapped_iterator_base BaseT
mapped_iterator_base(ItTy U)
ReferenceTy operator*() const
mapped_iterator()=default
const FuncTy & getFunction() const
mapped_iterator(ItTy U, FuncTy F)
ReferenceTy operator*() const
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
decltype(adl_rbegin(std::declval< Range & >())) check_has_free_function_rbegin
auto deref_or_none(const Iter &I, const Iter &End) -> std::optional< std::remove_const_t< std::remove_reference_t< decltype(*I)> > >
enumerator_result< decltype(*declval< Iters >())... > EnumeratorTupleType
decltype(std::declval< const T & >()==std::declval< const U & >()) has_equality_comparison
bool all_of_zip_predicate_first(Predicate &&P, Args &&...args)
const char unit< Period >::value[]
bool operator!=(const DenseSetImpl< ValueT, MapTy > &LHS, const DenseSetImpl< ValueT, MapTy > &RHS)
Inequality comparison for DenseSet.
static constexpr bool HasMemberFind
static constexpr bool HasFreeFunctionRBegin
decltype(adl_size(std::declval< Range & >())) check_has_free_function_size
static constexpr bool HasMemberContains
std::conditional_t< std::is_base_of_v< std::bidirectional_iterator_tag, typename std::iterator_traits< IterT >::iterator_category >, std::bidirectional_iterator_tag, std::forward_iterator_tag > fwd_or_bidi_tag
A type alias which is std::bidirectional_iterator_tag if the category of IterT derives from it,...
bool all_of_zip_predicate_last(std::tuple< ArgsThenPredicate... > argsThenPredicate, std::index_sequence< InputIndexes... >)
bool operator==(const DenseSetImpl< ValueT, MapTy > &LHS, const DenseSetImpl< ValueT, MapTy > &RHS)
Equality comparison for DenseSet.
decltype(std::declval< Range & >().contains(std::declval< const Element & >())) check_has_member_contains_t
decltype(adl_begin(std::declval< RangeT & >())) IterOfRange
decltype(sizeof(T)) has_sizeof
decltype(std::declval< Range & >().find(std::declval< const Element & >()) != std::declval< Range & >().end()) check_has_member_find_t
Iter next_or_end(const Iter &I, const Iter &End)
iterator_facade_base< ZipType, std::common_type_t< std::bidirectional_iterator_tag, typename std::iterator_traits< Iters >::iterator_category... >, ReferenceTupleType, typename std::iterator_traits< std::tuple_element_t< 0, std::tuple< Iters... > > >::difference_type, ReferenceTupleType *, ReferenceTupleType > zip_traits
static constexpr bool HasFreeFunctionSize
std::remove_reference_t< decltype(*adl_begin(std::declval< RangeT & >()))> ValueOfRange
std::conjunction< std::is_pointer< T >, std::is_trivially_copyable< typename std::iterator_traits< T >::value_type > > sort_trivially_copyable
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
detail::zippy< detail::zip_shortest, T, U, Args... > zip(T &&t, U &&u, Args &&...args)
zip iterator for two or more iteratable types.
constexpr auto not_equal_to(T &&Arg)
Functor variant of std::not_equal_to that can be used as a UnaryPredicate in functional algorithms li...
void stable_sort(R &&Range)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
void fill(R &&Range, T &&Value)
Provide wrappers to std::fill which take ranges instead of having to pass begin/end explicitly.
bool includes(R1 &&Range1, R2 &&Range2)
Provide wrappers to std::includes which take ranges instead of having to pass begin/end explicitly.
auto min_element(R &&Range)
Provide wrappers to std::min_element which take ranges instead of having to pass begin/end explicitly...
UnaryFunction for_each(R &&Range, UnaryFunction F)
Provide wrappers to std::for_each which take ranges instead of having to pass begin/end explicitly.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
detail::zip_longest_range< T, U, Args... > zip_longest(T &&t, U &&u, Args &&... args)
Iterate over two or more iterators at the same time.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
int(*)(const void *, const void *) get_array_pod_sort_comparator(const T &)
get_array_pod_sort_comparator - This is an internal helper function used to get type deduction of T r...
constexpr bool is_incomplete_v
Detects when type T is incomplete.
detail::zippy< detail::zip_first, T, U, Args... > zip_equal(T &&t, U &&u, Args &&...args)
zip iterator that assumes that all iteratees have the same length.
RelativeUniformCounterPtr Values
constexpr auto adl_begin(RangeT &&range) -> decltype(adl_detail::begin_impl(std::forward< RangeT >(range)))
Returns the begin iterator to range using std::begin and function found through Argument-Dependent Lo...
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
void interleave(ForwardIterator begin, ForwardIterator end, UnaryFunctor each_fn, NullaryFunctor between_fn)
An STL-style algorithm similar to std::for_each that applies a second functor between every pair of e...
constexpr bool all_types_equal_v
@ BinaryOp
One of the operands is a binary op.
auto accumulate(R &&Range, E &&Init)
Wrapper for std::accumulate.
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
int array_pod_sort_comparator(const void *P1, const void *P2)
Adapt std::less<T> for array_pod_sort.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
auto adjacent_find(R &&Range)
Provide wrappers to std::adjacent_find which finds the first pair of adjacent elements that are equal...
mapped_iterator< ItTy, FuncTy > map_iterator(ItTy I, FuncTy F)
decltype(auto) getSingleElement(ContainerTy &&C)
Asserts that the given container has a single element and returns that element.
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
bool hasNItemsOrLess(IterTy &&Begin, IterTy &&End, unsigned N, Pred &&ShouldBeCounted=[](const decltype(*std::declval< IterTy >()) &) { return true;})
Returns true if the sequence [Begin, End) has N or less items.
void interleaveComma(const Container &c, StreamT &os, UnaryFunctor each_fn)
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
void shuffle(Iterator first, Iterator last, RNG &&g)
constexpr auto adl_end(RangeT &&range) -> decltype(adl_detail::end_impl(std::forward< RangeT >(range)))
Returns the end iterator to range using std::end and functions found through Argument-Dependent Looku...
auto uninitialized_copy(R &&Src, IterTy Dst)
auto unique(Range &&R, Predicate P)
auto binary_search(R &&Range, T &&Value)
Provide wrappers to std::binary_search which take ranges instead of having to pass begin/end explicit...
auto upper_bound(R &&Range, T &&Value)
Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P)
Provide wrappers to std::copy_if which take ranges instead of having to pass begin/end explicitly.
constexpr auto equal_to(T &&Arg)
Functor variant of std::equal_to that can be used as a UnaryPredicate in functional algorithms like a...
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
constexpr auto bind_front(FnT &&Fn, BindArgsT &&...BindArgs)
C++20 bind_front.
constexpr auto adl_rbegin(RangeT &&range) -> decltype(adl_detail::rbegin_impl(std::forward< RangeT >(range)))
Returns the reverse-begin iterator to range using std::rbegin and function found through Argument-Dep...
bool hasNItemsOrMore(IterTy &&Begin, IterTy &&End, unsigned N, Pred &&ShouldBeCounted=[](const decltype(*std::declval< IterTy >()) &) { return true;}, std::enable_if_t< !std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< std::remove_reference_t< decltype(Begin)> >::iterator_category >::value, void > *=nullptr)
Return true if the sequence [Begin, End) has N or more items.
auto make_isa_range(RangeT &&Range)
Return a range over Range containing only elements for which isa<T> holds, casting each of them to T.
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto mismatch(R1 &&Range1, R2 &&Range2)
Provide wrappers to std::mismatch which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
constexpr size_t range_size(R &&Range)
Returns the size of the Range, i.e., the number of elements.
detail::zippy< detail::zip_first, T, U, Args... > zip_first(T &&t, U &&u, Args &&...args)
zip iterator that, for the sake of efficiency, assumes the first iteratee to be the shortest.
void sort(IteratorTy Start, IteratorTy End)
bool hasNItems(IterTy &&Begin, IterTy &&End, unsigned N, Pred &&ShouldBeCounted=[](const decltype(*std::declval< IterTy >()) &) { return true;}, std::enable_if_t< !std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< std::remove_reference_t< decltype(Begin)> >::iterator_category >::value, void > *=nullptr)
Return true if the sequence [Begin, End) has exactly N items.
auto find_if_not(R &&Range, UnaryPredicate P)
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
auto make_first_range(ContainerTy &&c)
Given a container of pairs, return a range over the first elements.
constexpr auto adl_size(RangeT &&range) -> decltype(adl_detail::size_impl(std::forward< RangeT >(range)))
Returns the size of range using std::size and functions found through Argument-Dependent Lookup (ADL)...
constexpr std::underlying_type_t< Enum > to_underlying(Enum E)
Returns underlying integer value of an enum.
constexpr bool is_sorted_constexpr(R &&Range, Cmp C=Cmp{})
Check if elements in a range R are sorted with respect to a comparator C.
bool is_sorted(R &&Range, Compare C)
Wrapper function around std::is_sorted to check if elements in a range R are sorted with respect to a...
bool hasSingleElement(ContainerTy &&C)
Returns true if the given container only contains a single element.
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
std::pair< T *, bool > find_singleton_nested(R &&Range, Predicate P, bool AllowRepeats=false)
Return a pair consisting of the single value in Range that satisfies P(<member of Range> ,...
std::conjunction< std::is_same< T, Ts >... > all_types_equal
traits class for checking whether type T is same as all other types in Ts.
T * find_singleton(R &&Range, Predicate P, bool AllowRepeats=false)
Return the single value in Range that satisfies P(<member of Range> *, AllowRepeats)->T * returning n...
auto search(R1 &&Range1, R2 &&Range2)
Provide wrappers to std::search which searches for the first occurrence of Range2 within Range1.
auto reverse_conditionally(ContainerTy &&C, bool ShouldReverse)
Return a range that conditionally reverses C.
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
auto drop_end(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the last N elements excluded.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
auto remove_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::remove_if which take ranges instead of having to pass begin/end explicitly.
std::disjunction< std::is_same< T, Ts >... > is_one_of
traits class for checking whether type T is one of any of the given types in the variadic list.
constexpr auto addEnumValues(EnumTy1 LHS, EnumTy2 RHS)
Helper which adds two underlying types of enumeration type.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
constexpr bool has_equality_comparison_v
Detects when type const T can be compared for equality with const U.
void replace(R &&Range, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace which take ranges instead of having to pass begin/end explicitly.
auto product_of(R &&Range, E Init=E{1})
Returns the product of all values in Range with Init initial value.
auto count(R &&Range, const E &Element)
Wrapper function around std::count to count the number of times an element Element occurs in the give...
DWARFExpression::Operation Op
auto max_element(R &&Range)
Provide wrappers to std::max_element which take ranges instead of having to pass begin/end explicitly...
OutputIt replace_copy_if(R &&Range, OutputIt Out, UnaryPredicate P, const T &NewValue)
Provide wrappers to std::replace_copy_if which take ranges instead of having to pass begin/end explic...
OutputIt copy(R &&Range, OutputIt Out)
auto partition(R &&Range, UnaryPredicate P)
Provide wrappers to std::partition which take ranges instead of having to pass begin/end explicitly.
auto make_second_range(ContainerTy &&c)
Given a container of pairs, return a range over the second elements.
auto sum_of(R &&Range, E Init=E{0})
Returns the sum of all values in Range with Init initial value.
typename detail::detector< void, Op, Args... >::value_t is_detected
Detects if a given trait holds for some set of arguments 'Args'.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
OutputIt replace_copy(R &&Range, OutputIt Out, const T &OldValue, const T &NewValue)
Provide wrappers to std::replace_copy which take ranges instead of having to pass begin/end explicitl...
auto count_if(R &&Range, UnaryPredicate P)
Wrapper function around std::count_if to count the number of times an element satisfying a given pred...
std::tuple_element_t< I, std::tuple< Ts... > > TypeAtIndex
Find the type at a given index in a list of types.
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
void erase_if(Container &C, UnaryPredicate P)
Provide a container algorithm similar to C++ Library Fundamentals v2's erase_if which is equivalent t...
constexpr auto adl_rend(RangeT &&range) -> decltype(adl_detail::rend_impl(std::forward< RangeT >(range)))
Returns the reverse-end iterator to range using std::rend and functions found through Argument-Depend...
void append_values(Container &C, Args &&...Values)
Appends all Values to container C.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
PointerUnion< const Value *, const PseudoSourceValue * > ValueType
bool all_equal(std::initializer_list< T > Values)
Returns true if all Values in the initializer lists are equal or the list.
void array_pod_sort(IteratorTy Start, IteratorTy End)
array_pod_sort - This sorts an array with the specified start and end extent.
constexpr decltype(auto) makeVisitor(CallableTs &&...Callables)
Returns an opaquely-typed Callable object whose operator() overload set is the sum of the operator() ...
filter_iterator_impl< WrappedIteratorT, PredicateT, detail::fwd_or_bidi_tag< WrappedIteratorT > > filter_iterator
Defines filter_iterator to a suitable specialization of filter_iterator_impl, based on the underlying...
bool equal(L &&LRange, R &&RRange)
Wrapper function around std::equal to detect if pair-wise elements between two ranges are the same.
std::conjunction< std::is_base_of< T, Ts >... > are_base_of
traits class for checking whether type T is a base class for all the given types in the variadic list...
constexpr detail::CastFunc< To > CastTo
bool all_of_zip(ArgsAndPredicate &&...argsAndPredicate)
Compare two zipped ranges using the provided predicate (as last argument).
constexpr detail::IsaCheckPredicate< Types... > IsaPred
Function object wrapper for the llvm::isa type check.
Implement std::hash so that hash_code can be used in STL containers.
Find the first index where a type appears in a list of types.
Determine if all types in Ts are distinct.
Binary functor that adapts to any other binary functor after dereferencing operands.
auto operator()(A &lhs, B &rhs) const
constexpr Visitor(HeadT &&Head, TailTs &&...Tail)
constexpr Visitor(HeadT &&Head)
std::optional< std::remove_const_t< std::remove_reference_t< decltype(*std::declval< Iter >())> > > type
std::tuple< typename ZipLongestItemType< Iters >::type... > type
std::tuple< decltype(*declval< Iters >())... > type
ItType< decltype(adl_begin( std::get< Ns >(declval< const std::tuple< Args... > & >())))... > type
ItType< decltype(adl_begin( std::get< Ns >(declval< std::tuple< Args... > & >())))... > type
Helper to obtain the iterator types for the tuple storage within zippy.
std::tuple< Refs... > range_reference_tuple
decltype(auto) value() const
Returns the value(s) for the current iterator.
static constexpr std::size_t NumValues
friend decltype(auto) get(const enumerator_result &Result)
Returns the value at index I.
static constexpr std::size_t NumRefs
std::tuple< std::size_t, Refs... > value_reference_tuple
friend bool operator==(const enumerator_result &Result, const std::tuple< std::size_t, Ts... > &Other)
std::size_t index() const
Returns the 0-based index of the current position within the original input range(s).
friend std::size_t get(const enumerator_result &Result)
Returns the value at index I. This case covers the index.
enumerator_result(std::size_t Index, Refs &&...Rs)
Tuple-like type for zip_enumerator dereference.
friend bool operator==(const index_iterator &Lhs, const index_iterator &Rhs)
std::ptrdiff_t operator-(const index_iterator &R) const
std::size_t operator*() const
friend bool operator<(const index_iterator &Lhs, const index_iterator &Rhs)
index_iterator & operator-=(std::ptrdiff_t N)
index_iterator & operator+=(std::ptrdiff_t N)
index_iterator(std::size_t Index)
Infinite stream of increasing 0-based size_t indices.
index_iterator begin() const
index_iterator end() const
zip_traits< ZipType, ReferenceTupleType, Iters... > Base
std::index_sequence_for< Iters... > IndexSequence
void tup_inc(std::index_sequence< Ns... >)
zip_common(Iters &&... ts)
bool test_all_equals(const zip_common &other, std::index_sequence< Ns... >) const
std::tuple< Iters... > iterators
value_type operator*() const
typename Base::value_type value_type
bool all_equals(zip_common &other)
Return true if all the iterator are matching other's iterators.
void tup_dec(std::index_sequence< Ns... >)
value_type deref(std::index_sequence< Ns... >) const
Zippy iterator that uses the second iterator for comparisons.
bool operator==(const zip_enumerator &Other) const
bool operator==(const zip_first &other) const
bool operator==(const zip_shortest &other) const
std::tuple_element_t< Index, std::tuple< Args... > > arg_t
The type of an argument to this function.
ReturnType result_t
The result type of this function.
std::tuple_element_t< i, std::tuple< Args... > > arg_t
The type of an argument to this function.
ReturnType result_t
The result type of this function.
This class provides various trait information about a callable object.
Function object to check whether the first component of a container supported by std::get (like std::...
bool operator()(const T &lhs, const T &rhs) const
Function object to check whether the second component of a container supported by std::get (like std:...
bool operator()(const T &lhs, const T &rhs) const
std::add_pointer_t< std::add_const_t< T > > type
std::add_lvalue_reference_t< std::add_const_t< T > > type
Function object to apply a binary function to the first component of a std::pair.
size_t operator()(const std::pair< First, Second > &P) const
Utility type to build an inheritance chain that makes it easy to rank overload candidates.