diff options
| -rw-r--r-- | llvm/include/llvm/ADT/STLExtras.h | 17 | ||||
| -rw-r--r-- | llvm/unittests/ADT/RangeAdapterTest.cpp | 30 |
2 files changed, 43 insertions, 4 deletions
diff --git a/llvm/include/llvm/ADT/STLExtras.h b/llvm/include/llvm/ADT/STLExtras.h index 00b796f6381..8e4d186d15a 100644 --- a/llvm/include/llvm/ADT/STLExtras.h +++ b/llvm/include/llvm/ADT/STLExtras.h @@ -209,10 +209,19 @@ inline mapped_iterator<ItTy, FuncTy> map_iterator(const ItTy &I, FuncTy F) { } /// \brief Metafunction to determine if type T has a member called rbegin(). -template <typename T> struct has_rbegin { - template <typename U> static char(&f(const U &, decltype(&U::rbegin)))[1]; - static char(&f(...))[2]; - const static bool value = sizeof(f(std::declval<T>(), nullptr)) == 1; +template <typename Ty> +class has_rbegin { + typedef char yes[1]; + typedef char no[2]; + + template <typename Inner> + static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr); + + template <typename> + static no& test(...); + +public: + static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); }; // Returns an iterator_range over the given container which iterates in reverse. diff --git a/llvm/unittests/ADT/RangeAdapterTest.cpp b/llvm/unittests/ADT/RangeAdapterTest.cpp index 634f5bb990d..a4e922ecf9a 100644 --- a/llvm/unittests/ADT/RangeAdapterTest.cpp +++ b/llvm/unittests/ADT/RangeAdapterTest.cpp @@ -27,8 +27,11 @@ public: ReverseOnlyVector(std::initializer_list<int> list) : Vec(list) {} typedef std::vector<int>::reverse_iterator reverse_iterator; + typedef std::vector<int>::const_reverse_iterator const_reverse_iterator; reverse_iterator rbegin() { return Vec.rbegin(); } reverse_iterator rend() { return Vec.rend(); } + const_reverse_iterator rbegin() const { return Vec.rbegin(); } + const_reverse_iterator rend() const { return Vec.rend(); } }; // A wrapper around vector which exposes begin(), end(), rbegin() and rend(). @@ -49,6 +52,29 @@ public: reverse_iterator rend() { return Vec.rend(); } }; +/// This is the same as BidirectionalVector but with the addition of const +/// begin/rbegin methods to ensure that the type traits for has_rbegin works. +class BidirectionalVectorConsts { + std::vector<int> Vec; + +public: + BidirectionalVectorConsts(std::initializer_list<int> list) : Vec(list) {} + + typedef std::vector<int>::iterator iterator; + typedef std::vector<int>::const_iterator const_iterator; + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + typedef std::vector<int>::reverse_iterator reverse_iterator; + typedef std::vector<int>::const_reverse_iterator const_reverse_iterator; + reverse_iterator rbegin() { return Vec.rbegin(); } + reverse_iterator rend() { return Vec.rend(); } + const_reverse_iterator rbegin() const { return Vec.rbegin(); } + const_reverse_iterator rend() const { return Vec.rend(); } +}; + template <typename R> void TestRev(const R &r) { int counter = 3; for (int i : r) @@ -80,4 +106,8 @@ TYPED_TEST(RangeAdapterRValueTest, TrivialOperation) { TestRev(reverse(TypeParam({0, 1, 2, 3}))); } +TYPED_TEST(RangeAdapterRValueTest, HasRbegin) { + EXPECT_TRUE(has_rbegin<TypeParam>::value); +} + } // anonymous namespace |

