summaryrefslogtreecommitdiffstats
path: root/llvm/include
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/include')
-rw-r--r--llvm/include/llvm/ADT/STLExtras.h8
-rw-r--r--llvm/include/llvm/ADT/iterator_range.h34
2 files changed, 39 insertions, 3 deletions
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h
index 274933bc520..430707cbd79 100644
--- a/llvm/include/llvm/ADT/STLExtras.h
+++ b/llvm/include/llvm/ADT/STLExtras.h
@@ -1573,6 +1573,14 @@ template <class Ptr> auto to_address(const Ptr &P) -> decltype(P.operator->()) {
}
template <class T> constexpr T *to_address(T *P) { return P; }
+template <typename R>
+auto index(R &&TheRange,
+ typename std::iterator_traits<detail::IterOfRange<R>>::difference_type N)
+ -> decltype(TheRange.begin()[N]) {
+ assert(N < TheRange.end() - TheRange.begin() && "Index out of range!");
+ return TheRange.begin()[N];
+}
+
} // end namespace llvm
#endif // LLVM_ADT_STLEXTRAS_H
diff --git a/llvm/include/llvm/ADT/iterator_range.h b/llvm/include/llvm/ADT/iterator_range.h
index 774c7c4e336..3bb9231441c 100644
--- a/llvm/include/llvm/ADT/iterator_range.h
+++ b/llvm/include/llvm/ADT/iterator_range.h
@@ -20,9 +20,17 @@
#include <iterator>
#include <utility>
+#include <cassert>
namespace llvm {
+template <typename T>
+constexpr bool is_random_iterator() {
+ return std::is_same<
+ typename std::iterator_traits<T>::iterator_category,
+ std::random_access_iterator_tag>::value;
+}
+
/// A range adaptor for a pair of iterators.
///
/// This just wraps two iterators into a range-compatible interface. Nothing
@@ -58,11 +66,31 @@ template <typename T> iterator_range<T> make_range(std::pair<T, T> p) {
return iterator_range<T>(std::move(p.first), std::move(p.second));
}
+/// Non-random-iterator version
template <typename T>
-iterator_range<decltype(adl_begin(std::declval<T>()))> drop_begin(T &&t,
- int n) {
- return make_range(std::next(adl_begin(t), n), adl_end(t));
+auto drop_begin(T &&t, int n) ->
+ typename std::enable_if<!is_random_iterator<decltype(adl_begin(t))>(),
+ iterator_range<decltype(adl_begin(t))>>::type {
+ auto begin = adl_begin(t);
+ auto end = adl_end(t);
+ for (int i = 0; i < n; i++) {
+ assert(begin != end);
+ ++begin;
+ }
+ return make_range(begin, end);
}
+
+/// Optimized version for random iterators
+template <typename T>
+auto drop_begin(T &&t, int n) ->
+ typename std::enable_if<is_random_iterator<decltype(adl_begin(t))>(),
+ iterator_range<decltype(adl_begin(t))>>::type {
+ auto begin = adl_begin(t);
+ auto end = adl_end(t);
+ assert(end - begin >= n && "Dropping more elements than exist!");
+ return make_range(std::next(begin, n), end);
+}
+
}
#endif
OpenPOWER on IntegriCloud