diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h index 00b796f6381..8e4d186d15a 100644 --- a/include/llvm/ADT/STLExtras.h +++ b/include/llvm/ADT/STLExtras.h @@ -209,10 +209,19 @@ inline mapped_iterator map_iterator(const ItTy &I, FuncTy F) { } /// \brief Metafunction to determine if type T has a member called rbegin(). -template struct has_rbegin { - template static char(&f(const U &, decltype(&U::rbegin)))[1]; - static char(&f(...))[2]; - const static bool value = sizeof(f(std::declval(), nullptr)) == 1; +template +class has_rbegin { + typedef char yes[1]; + typedef char no[2]; + + template + static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr); + + template + static no& test(...); + +public: + static const bool value = sizeof(test(nullptr)) == sizeof(yes); }; // Returns an iterator_range over the given container which iterates in reverse. diff --git a/unittests/ADT/RangeAdapterTest.cpp b/unittests/ADT/RangeAdapterTest.cpp index 634f5bb990d..a4e922ecf9a 100644 --- a/unittests/ADT/RangeAdapterTest.cpp +++ b/unittests/ADT/RangeAdapterTest.cpp @@ -27,8 +27,11 @@ public: ReverseOnlyVector(std::initializer_list list) : Vec(list) {} typedef std::vector::reverse_iterator reverse_iterator; + typedef std::vector::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 Vec; + +public: + BidirectionalVectorConsts(std::initializer_list list) : Vec(list) {} + + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + iterator begin(); + iterator end(); + const_iterator begin() const; + const_iterator end() const; + + typedef std::vector::reverse_iterator reverse_iterator; + typedef std::vector::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 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::value); +} + } // anonymous namespace