[PATCH] D58088: [adt] Add raw_pointer_iterator to iterate over std::unique_ptr<> collections

Daniel Sanders via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Feb 11 16:36:24 PST 2019


dsanders created this revision.
dsanders added reviewers: bogner, volkan, aditya_nandakumar, paquette, aemerson.
Herald added subscribers: kristina, dexonsmith.
Herald added a project: LLVM.

raw_pointer_iterator adapts the usual iterator by calling get() on the
value when being dereferenced. This allows users to iterate over things
like std::vector<std::unique_ptr<foo>> while preserving ownership and not
calling the deleted copy constructor.

This is similar to pointer_iterator except that pointer_iterator will attempt
to copy the pointer which is not possible for unique_ptr.


Repository:
  rL LLVM

https://reviews.llvm.org/D58088

Files:
  include/llvm/ADT/iterator.h
  unittests/ADT/IteratorTest.cpp


Index: unittests/ADT/IteratorTest.cpp
===================================================================
--- unittests/ADT/IteratorTest.cpp
+++ unittests/ADT/IteratorTest.cpp
@@ -297,6 +297,38 @@
     EXPECT_EQ(A + I++, P);
 }
 
+TEST(RawPointerIterator, Basic) {
+  std::unique_ptr<int> A[] = {
+      make_unique<int>(1),
+      make_unique<int>(2),
+      make_unique<int>(3),
+      make_unique<int>(4),
+  };
+  raw_pointer_iterator<std::unique_ptr<int> *> Begin(std::begin(A)),
+      End(std::end(A));
+  EXPECT_EQ(A->get(), *Begin);
+  ++Begin;
+  EXPECT_EQ((A + 1)->get(), *Begin);
+  ++Begin;
+  EXPECT_EQ((A + 2)->get(), *Begin);
+  ++Begin;
+  EXPECT_EQ((A + 3)->get(), *Begin);
+  ++Begin;
+  EXPECT_EQ(Begin, End);
+}
+
+TEST(RawPointerIterator, Range) {
+  std::unique_ptr<int> A[] = {
+      make_unique<int>(1),
+      make_unique<int>(2),
+      make_unique<int>(3),
+      make_unique<int>(4),
+  };
+  int I = 0;
+  for (int *P : make_raw_pointer_range(A))
+    EXPECT_EQ((A + I++)->get(), P);
+}
+
 TEST(ZipIteratorTest, Basic) {
   using namespace std;
   const SmallVector<unsigned, 6> pi{3, 1, 4, 1, 5, 9};
Index: include/llvm/ADT/iterator.h
===================================================================
--- include/llvm/ADT/iterator.h
+++ include/llvm/ADT/iterator.h
@@ -361,6 +361,34 @@
   }
 };
 
+// Iterator to convert std::unique_ptr to raw pointers.
+template <typename WrappedIteratorT,
+          typename T = typename std::remove_reference<decltype(*std::declval<WrappedIteratorT>())>::type::pointer>
+class raw_pointer_iterator
+    : public iterator_adaptor_base<
+          raw_pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT,
+          typename std::iterator_traits<WrappedIteratorT>::iterator_category,
+          T> {
+  mutable T Ptr;
+
+public:
+  raw_pointer_iterator() = default;
+
+  explicit raw_pointer_iterator(WrappedIteratorT u)
+      : raw_pointer_iterator::iterator_adaptor_base(std::move(u)) {}
+
+  T &operator*() { return Ptr = this->I->get(); }
+  const T &operator*() const { return Ptr = this->I->get(); }
+};
+
+template <typename RangeT, typename WrappedIteratorT =
+                               decltype(std::begin(std::declval<RangeT>()))>
+iterator_range<raw_pointer_iterator<WrappedIteratorT>>
+make_raw_pointer_range(RangeT &&Range) {
+  using RawPointerIteratorT = raw_pointer_iterator<WrappedIteratorT>;
+  return make_range(RawPointerIteratorT(std::begin(std::forward<RangeT>(Range))),
+                    RawPointerIteratorT(std::end(std::forward<RangeT>(Range))));
+}
 } // end namespace llvm
 
 #endif // LLVM_ADT_ITERATOR_H


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D58088.186368.patch
Type: text/x-patch
Size: 2616 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190212/10f178ff/attachment.bin>


More information about the llvm-commits mailing list