Index: include/llvm/ADT/STLExtras.h =================================================================== --- include/llvm/ADT/STLExtras.h +++ include/llvm/ADT/STLExtras.h @@ -196,12 +196,16 @@ mapped_iterator(ItTy U, FuncTy F) : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {} + // Constructor for the end iterator. Not dereferencable, hence no FuncTy. + mapped_iterator(ItTy U) + : mapped_iterator::iterator_adaptor_base(std::move(U)) {} + ItTy getCurrent() { return this->I; } - FuncReturnTy operator*() { return F(*this->I); } + FuncReturnTy operator*() { return (*F)(*this->I); } private: - FuncTy F; + Optional F; }; // map_iterator - Provide a convenient way to create mapped_iterators, just like @@ -211,6 +215,20 @@ return mapped_iterator(std::move(I), std::move(F)); } +template +using mapped_iterator_range = iterator_range>; + +/// Convenience function that takes a range of elements and a predicate, +/// and return a new mapped_iterator range. +template +mapped_iterator_range, PredicateT> +make_mapped_range(RangeT &&Range, PredicateT Pred) { + using MappedItT = mapped_iterator, PredicateT>; + auto I = MappedItT(std::begin(std::forward(Range)), std::move(Pred)); + auto E = MappedItT(std::end(std::forward(Range))); + return make_range(I, E); +} + /// Helper to determine if type T has a member called rbegin(). template class has_rbegin_impl { using yes = char[1]; Index: unittests/ADT/MappedIteratorTest.cpp =================================================================== --- unittests/ADT/MappedIteratorTest.cpp +++ unittests/ADT/MappedIteratorTest.cpp @@ -48,4 +48,12 @@ EXPECT_EQ(M[1], 42) << "assignment should have modified M"; } +TEST(MappedIteratorTest, MappedRange) { + std::vector V({0, 1, 2}); + + size_t I = 1; + for (int Val : make_mapped_range(V, [](int X) { return X + 1; })) + EXPECT_EQ(Val, I++) << "should have applied function in dereference"; +} + } // anonymous namespace