瀏覽代碼

refactor: clang-format change

Sam Jaffe 2 年之前
父節點
當前提交
5468a8168f

+ 1 - 1
.clang-format

@@ -75,7 +75,7 @@ KeepEmptyLinesAtTheStartOfBlocks: true
 MacroBlockBegin: ''
 MacroBlockEnd:   ''
 MaxEmptyLinesToKeep: 1
-NamespaceIndentation: All
+NamespaceIndentation: Inner
 ObjCBlockIndentWidth: 2
 ObjCSpaceAfterProperty: false
 ObjCSpaceBeforeProtocolList: true

+ 54 - 55
include/stream/detail/self_iterating_container.hpp

@@ -1,59 +1,58 @@
 #pragma once
 
 namespace stream::detail {
-  template <typename C, typename It = typename C::const_iterator>
-  class self_iterating_container {
-  private:
-    std::ptrdiff_t offset{0};
-    C container;
-    It current;
-    It end;
-
-  public:
-    self_iterating_container() = default;
-    self_iterating_container(C const & container)
-        : container(container), current(container.cbegin()),
-          end(container.cend()) {}
-
-    self_iterating_container(C && container)
-        : container(std::move(container)), current(container.cbegin()),
-          end(container.cend()) {}
-
-    self_iterating_container(self_iterating_container const & other) {
-      *this = other;
-    }
-
-    self_iterating_container(self_iterating_container && other) {
-      *this = std::move(other);
-    }
-
-    self_iterating_container &
-    operator=(self_iterating_container const & other) {
-      offset = other.offset;
-      container = other.container;
-      setup();
-      return *this;
-    }
-
-    self_iterating_container & operator=(self_iterating_container && other) {
-      offset = other.offset;
-      container = std::move(other.container);
-      setup();
-      return *this;
-    }
-
-    void operator++() {
-      ++offset;
-      ++current;
-    }
-    auto & operator*() const { return *current; }
-    operator bool() const { return current != end; }
-
-  private:
-    void setup() {
-      current = container.cbegin();
-      end = container.cend();
-      std::advance(current, offset);
-    }
-  };
+template <typename C, typename It = typename C::const_iterator>
+class self_iterating_container {
+private:
+  std::ptrdiff_t offset{0};
+  C container;
+  It current;
+  It end;
+
+public:
+  self_iterating_container() = default;
+  self_iterating_container(C const & container)
+      : container(container), current(container.cbegin()),
+        end(container.cend()) {}
+
+  self_iterating_container(C && container)
+      : container(std::move(container)), current(container.cbegin()),
+        end(container.cend()) {}
+
+  self_iterating_container(self_iterating_container const & other) {
+    *this = other;
+  }
+
+  self_iterating_container(self_iterating_container && other) {
+    *this = std::move(other);
+  }
+
+  self_iterating_container & operator=(self_iterating_container const & other) {
+    offset = other.offset;
+    container = other.container;
+    setup();
+    return *this;
+  }
+
+  self_iterating_container & operator=(self_iterating_container && other) {
+    offset = other.offset;
+    container = std::move(other.container);
+    setup();
+    return *this;
+  }
+
+  void operator++() {
+    ++offset;
+    ++current;
+  }
+  auto & operator*() const { return *current; }
+  operator bool() const { return current != end; }
+
+private:
+  void setup() {
+    current = container.cbegin();
+    end = container.cend();
+    std::advance(current, offset);
+  }
+};
 }

+ 47 - 47
include/stream/filter.hpp

@@ -4,63 +4,63 @@
 #include <stream/iterator.hpp>
 
 namespace stream::detail {
-  template <typename T> class filter_iterator {
-  public:
-    filter_iterator(std::function<bool(T const &)> f, iterator<T> && impl,
-                    iterator<T> && end)
-        : pred_(f), impl_(std::forward<iterator<T>>(impl)),
-          end_(std::forward<iterator<T>>(end)) {
-      advance();
-    }
+template <typename T> class filter_iterator {
+public:
+  filter_iterator(std::function<bool(T const &)> f, iterator<T> && impl,
+                  iterator<T> && end)
+      : pred_(f), impl_(std::forward<iterator<T>>(impl)),
+        end_(std::forward<iterator<T>>(end)) {
+    advance();
+  }
 
-    T operator*() { return mem_; }
+  T operator*() { return mem_; }
 
-    filter_iterator & operator++() {
-      ++impl_;
-      advance();
-      return *this;
-    }
+  filter_iterator & operator++() {
+    ++impl_;
+    advance();
+    return *this;
+  }
 
-    bool operator==(filter_iterator const & rhs) const {
-      return impl_ == rhs.impl_;
-    }
+  bool operator==(filter_iterator const & rhs) const {
+    return impl_ == rhs.impl_;
+  }
 
-  private:
-    void advance() {
-      while (impl_ != end_ && !pred_(mem_ = *impl_)) {
-        ++impl_;
-      }
+private:
+  void advance() {
+    while (impl_ != end_ && !pred_(mem_ = *impl_)) {
+      ++impl_;
     }
+  }
 
-    std::function<bool(T const &)> pred_;
-    ref_or_val<T> mem_; // To avoid re-calcs, we store this
-    iterator<T> impl_, end_;
-  };
+  std::function<bool(T const &)> pred_;
+  ref_or_val<T> mem_; // To avoid re-calcs, we store this
+  iterator<T> impl_, end_;
+};
 
-  template <typename T> class filter_stream {
-  public:
-    template <typename F>
-    filter_stream(F && func, stream_base<T> const & sb)
-        : pred_(func), source_(sb) {}
+template <typename T> class filter_stream {
+public:
+  template <typename F>
+  filter_stream(F && func, stream_base<T> const & sb)
+      : pred_(func), source_(sb) {}
 
-    iterator<T> begin() { return ::iterator::filter_iterator(pred_, source_); }
+  iterator<T> begin() { return ::iterator::filter_iterator(pred_, source_); }
 
-    iterator<T> end() { return ::iterator::filter_iterator<iterator<T>>(); }
+  iterator<T> end() { return ::iterator::filter_iterator<iterator<T>>(); }
 
-  private:
-    typename ::iterator::filter_iterator<iterator<T>>::predicate_t pred_;
-    stream_base<T> source_;
-  };
+private:
+  typename ::iterator::filter_iterator<iterator<T>>::predicate_t pred_;
+  stream_base<T> source_;
+};
 
-  template <typename T>
-  template <typename F>
-  auto stream_base<T>::filter(F && pred) && -> stream_base<T> {
-    return std::make_shared<filter_stream<T>>(pred, std::move(*this));
-  }
+template <typename T>
+template <typename F>
+auto stream_base<T>::filter(F && pred) && -> stream_base<T> {
+  return std::make_shared<filter_stream<T>>(pred, std::move(*this));
+}
 
-  template <typename T>
-  template <typename F>
-  auto stream_base<T>::filter(F && pred) const & -> stream_base<T> {
-    return std::make_shared<filter_stream<T>>(pred, *this);
-  }
+template <typename T>
+template <typename F>
+auto stream_base<T>::filter(F && pred) const & -> stream_base<T> {
+  return std::make_shared<filter_stream<T>>(pred, *this);
+}
 }

+ 8 - 8
include/stream/forward.hpp

@@ -3,15 +3,15 @@
 #include "traits.hpp"
 
 namespace stream::detail {
-  template <typename> class stream_base;
-  template <typename> class iterator_impl;
+template <typename> class stream_base;
+template <typename> class iterator_impl;
 }
 
 namespace stream {
-  template <typename> class iterator;
-  template <typename, typename> struct map_t;
-  template <typename> struct filter_t;
-  template <typename, typename> struct flatmap_t;
-  template <typename T>
-  using stream = detail::stream_base<T>; // Should I override instead?
+template <typename> class iterator;
+template <typename, typename> struct map_t;
+template <typename> struct filter_t;
+template <typename, typename> struct flatmap_t;
+template <typename T>
+using stream = detail::stream_base<T>; // Should I override instead?
 }

+ 27 - 29
include/stream/iterator.hpp

@@ -11,37 +11,35 @@
 #include <iterator/facade.h>
 
 namespace stream {
-  template <typename T>
-  class iterator : public ::iterator::facade<iterator<T>> {
-  private:
-    T (*dereference_)(void *){nullptr};
-    bool (*equal_to_)(void *, void *){nullptr};
-    void (*increment_)(void *){nullptr};
-    char const * type_{nullptr};
-    detail::ifd_pointer impl_{};
-
-  public:
-    iterator() = default;
-
-    template <typename Iter>
-    iterator(Iter impl)
-        : dereference_([](void * p) -> T { return **((Iter *)p); }),
-          equal_to_(
-              [](void * l, void * r) { return *((Iter *)l) == *((Iter *)r); }),
-          increment_([](void * p) { ++(*(Iter *)(p)); }),
-          type_(typeid(Iter).name()), impl_(std::forward<Iter>(impl)) {}
-
-    T dereference() const { return dereference_(impl_.get()); }
-    void increment() { increment_(impl_.get()); }
-    bool equal_to(iterator const & other) const {
-      return impl_ == other.impl_ ||
-             (impl_ && other.impl_ &&
-              equal_to_(impl_.get(), other.impl_.get()));
-    }
-  };
+template <typename T> class iterator : public ::iterator::facade<iterator<T>> {
+private:
+  T (*dereference_)(void *){nullptr};
+  bool (*equal_to_)(void *, void *){nullptr};
+  void (*increment_)(void *){nullptr};
+  char const * type_{nullptr};
+  detail::ifd_pointer impl_{};
+
+public:
+  iterator() = default;
 
   template <typename Iter>
-  iterator(Iter) -> iterator<typename std::iterator_traits<Iter>::reference>;
+  iterator(Iter impl)
+      : dereference_([](void * p) -> T { return **((Iter *)p); }),
+        equal_to_(
+            [](void * l, void * r) { return *((Iter *)l) == *((Iter *)r); }),
+        increment_([](void * p) { ++(*(Iter *)(p)); }),
+        type_(typeid(Iter).name()), impl_(std::forward<Iter>(impl)) {}
+
+  T dereference() const { return dereference_(impl_.get()); }
+  void increment() { increment_(impl_.get()); }
+  bool equal_to(iterator const & other) const {
+    return impl_ == other.impl_ ||
+           (impl_ && other.impl_ && equal_to_(impl_.get(), other.impl_.get()));
+  }
+};
+
+template <typename Iter>
+iterator(Iter) -> iterator<typename std::iterator_traits<Iter>::reference>;
 }
 
 MAKE_ITERATOR_FACADE_TYPEDEFS_T(::stream::iterator);

+ 52 - 52
include/stream/make_stream.hpp

@@ -5,63 +5,63 @@
 #include "source.hpp"
 
 namespace stream {
-  /**
-   * Construct a stream out of the given container. If C && is an rvalue
-   * reference, the returned object will take ownership of cont. Otherwise, we
-   * capture cont by reference to maximise performance.
-   */
-  template <typename C>
-  auto of(C && cont) -> detail::stream_base<decltype(*cont.begin())> {
-    return std::make_shared<detail::source_stream<C>>(std::forward<C>(cont));
-  }
+/**
+ * Construct a stream out of the given container. If C && is an rvalue
+ * reference, the returned object will take ownership of cont. Otherwise, we
+ * capture cont by reference to maximise performance.
+ */
+template <typename C>
+auto of(C && cont) -> detail::stream_base<decltype(*cont.begin())> {
+  return std::make_shared<detail::source_stream<C>>(std::forward<C>(cont));
+}
 
-  template <typename T> detail::stream_base<T &> empty() {
-    return std::make_shared<detail::range_stream<T *>>(nullptr, nullptr);
-  }
+template <typename T> detail::stream_base<T &> empty() {
+  return std::make_shared<detail::range_stream<T *>>(nullptr, nullptr);
+}
 
-  /**
-   * Construct a single element stream containing the pointer given
-   */
-  template <typename T> detail::stream_base<T &> of(T * ptr) {
-    return std::make_shared<detail::range_stream<T *>>(ptr, ptr + 1);
-  }
+/**
+ * Construct a single element stream containing the pointer given
+ */
+template <typename T> detail::stream_base<T &> of(T * ptr) {
+  return std::make_shared<detail::range_stream<T *>>(ptr, ptr + 1);
+}
 
-  /**
-   * Construct a stream from input iterators representing the start and end
-   * Requirements: It must be an iterator type that provides the trait
-   * 'reference'
-   */
-  template <typename It>
-  detail::stream_base<typename It::reference> of(It begin, It end) {
-    return std::make_shared<detail::range_stream<It>>(begin, end);
-  }
+/**
+ * Construct a stream from input iterators representing the start and end
+ * Requirements: It must be an iterator type that provides the trait
+ * 'reference'
+ */
+template <typename It>
+detail::stream_base<typename It::reference> of(It begin, It end) {
+  return std::make_shared<detail::range_stream<It>>(begin, end);
+}
 
-  /**
-   * Construct a stream given certain start and end bounds.
-   * e.g. stream::make_range_stream(0, 10)
-   */
-  template <typename T> detail::stream_base<T &> range(T start, T const & end) {
-    std::vector<T> vec;
-    vec.reserve(end - start);
-    while (start < end) {
-      vec.emplace_back(start++);
-    }
-    return make_stream(std::move(vec));
+/**
+ * Construct a stream given certain start and end bounds.
+ * e.g. stream::make_range_stream(0, 10)
+ */
+template <typename T> detail::stream_base<T &> range(T start, T const & end) {
+  std::vector<T> vec;
+  vec.reserve(end - start);
+  while (start < end) {
+    vec.emplace_back(start++);
   }
+  return make_stream(std::move(vec));
+}
 
-  /**
-   * Construct a stream given certain start and end bounds, as well as an
-   * increment amount. e.g. stream::make_range_stream(0, 10, 2)
-   */
-  template <typename T>
-  detail::stream_base<T &> range(T start, T const & end, T const & increment) {
-    int elems{(end - start) / increment};
-    if (elems < 0 || end == start) { return {}; }
-    std::vector<T> vec{start};
-    vec.reserve(elems + 1);
-    while (elems-- > 0) {
-      vec.emplace_back(start += increment);
-    }
-    return make_stream(std::move(vec));
+/**
+ * Construct a stream given certain start and end bounds, as well as an
+ * increment amount. e.g. stream::make_range_stream(0, 10, 2)
+ */
+template <typename T>
+detail::stream_base<T &> range(T start, T const & end, T const & increment) {
+  int elems{(end - start) / increment};
+  if (elems < 0 || end == start) { return {}; }
+  std::vector<T> vec{start};
+  vec.reserve(elems + 1);
+  while (elems-- > 0) {
+    vec.emplace_back(start += increment);
   }
+  return make_stream(std::move(vec));
+}
 }

+ 33 - 35
include/stream/map.hpp

@@ -3,48 +3,46 @@
 #include <iterator/proxy.h>
 
 namespace stream::detail {
-  template <typename T, typename R>
-  class map_iterator
-      : public ::iterator::proxy<iterator<T>, map_iterator<T, R>> {
-  public:
-    using projection_t = std::function<R(T const &)>;
-    using super_t = ::iterator::proxy<iterator<T>, map_iterator<T, R>>;
+template <typename T, typename R>
+class map_iterator : public ::iterator::proxy<iterator<T>, map_iterator<T, R>> {
+public:
+  using projection_t = std::function<R(T const &)>;
+  using super_t = ::iterator::proxy<iterator<T>, map_iterator<T, R>>;
 
-  public:
-    map_iterator(projection_t proj, iterator<T> && impl)
-        : proj_(std::move(proj)), super_t(std::move(impl)) {}
+public:
+  map_iterator(projection_t proj, iterator<T> && impl)
+      : proj_(std::move(proj)), super_t(std::move(impl)) {}
 
-    R dereference() const { return proj_(super_t::dereference()); }
+  R dereference() const { return proj_(super_t::dereference()); }
 
-  private:
-    std::function<R(T const &)> proj_;
-  };
+private:
+  std::function<R(T const &)> proj_;
+};
 
-  template <typename T, typename R> class map_stream {
-  public:
-    template <typename F>
-    map_stream(F && func, stream_base<T> const & sb)
-        : fun_(func), source_(sb) {}
+template <typename T, typename R> class map_stream {
+public:
+  template <typename F>
+  map_stream(F && func, stream_base<T> const & sb) : fun_(func), source_(sb) {}
 
-    iterator<R> begin() { return {map_iterator<T, R>{fun_, source_.begin()}}; }
+  iterator<R> begin() { return {map_iterator<T, R>{fun_, source_.begin()}}; }
 
-    iterator<R> end() { return {map_iterator<T, R>{fun_, source_.end()}}; }
+  iterator<R> end() { return {map_iterator<T, R>{fun_, source_.end()}}; }
 
-  private:
-    std::function<R(T const &)> fun_;
-    stream_base<T> source_;
-  };
+private:
+  std::function<R(T const &)> fun_;
+  stream_base<T> source_;
+};
 
-  template <typename T>
-  template <typename F>
-  stream_base<traits::mapped_t<T, F>> stream_base<T>::map(F && func) && {
-    return std::make_shared<map_stream<T, traits::mapped_t<T, F>>>(
-        func, std::move(*this));
-  }
+template <typename T>
+template <typename F>
+stream_base<traits::mapped_t<T, F>> stream_base<T>::map(F && func) && {
+  return std::make_shared<map_stream<T, traits::mapped_t<T, F>>>(
+      func, std::move(*this));
+}
 
-  template <typename T>
-  template <typename F>
-  stream_base<traits::mapped_t<T, F>> stream_base<T>::map(F && func) const & {
-    return std::make_shared<map_stream<T, traits::mapped_t<T, F>>>(func, *this);
-  }
+template <typename T>
+template <typename F>
+stream_base<traits::mapped_t<T, F>> stream_base<T>::map(F && func) const & {
+  return std::make_shared<map_stream<T, traits::mapped_t<T, F>>>(func, *this);
+}
 }

+ 144 - 145
include/stream/stream_base.hpp

@@ -9,149 +9,148 @@
 #include "iterator.hpp"
 
 namespace stream::detail {
-  template <typename T, typename = void> class stream_base_pointer_impl {};
-
-  template <typename T>
-  class stream_base_pointer_impl<
-      T, std::enable_if_t<traits::is_dereferencable_v<T>>> {
-  private:
-    using self_t = stream_base<T>;
-    using pointer = typename std::remove_reference<T>::type;
-    using element_type = typename std::pointer_traits<pointer>::element_type;
-
-  public:
-    auto deref() const & -> stream_base<element_type &> {
-      return static_cast<self_t const *>(this)->map(
-          [](T const & p) -> element_type & { return *p; });
-    }
-
-    auto deref() && -> stream_base<element_type &> {
-      return static_cast<self_t &&>(*this).map(
-          [](T const & p) -> element_type & { return *p; });
-    }
-  };
-
-  template <typename T> class stream_base : public stream_base_pointer_impl<T> {
-  private:
-    using value_type = typename std::decay<T>::type;
-
-  public:
-    template <typename Stream> stream_base(std::shared_ptr<Stream> && impl) {
-      do_begin = [](std::shared_ptr<void> p) -> iterator<T> {
-        return std::static_pointer_cast<Stream>(p)->begin();
-      };
-      do_end = [](std::shared_ptr<void> p) -> iterator<T> {
-        return std::static_pointer_cast<Stream>(p)->end();
-      };
-      impl_ = std::static_pointer_cast<void>(impl);
-    }
-
-    ::stream::iterator<T> begin() const { return do_begin(impl_); }
-    ::stream::iterator<T> end() const { return do_end(impl_); }
-
-    bool empty() const { return begin() == end(); }
-
-    std::vector<value_type> collect() const {
-      std::vector<value_type> coll;
-      collect(coll);
-      return coll;
-    }
-
-    template <typename C, typename = std::enable_if_t<
-                              !std::is_void_v<typename C::value_type>>>
-    C & collect(C & coll) const {
-      std::copy(begin(), end(), std::inserter(coll, coll.end()));
-      return coll;
-    }
-
-    std::optional<value_type> first() const {
-      return begin() != end() ? std::optional(*begin()) : std::nullopt;
-    }
-
-    template <typename F> bool none(F && pred) const {
-      return std::none_of(begin(), end(), pred);
-    }
-
-    template <typename F> bool all(F && pred) const {
-      return std::all_of(begin(), end(), pred);
-    }
-
-    template <typename F> bool any(F && pred) const {
-      return std::any_of(begin(), end(), pred);
-    }
-
-    template <typename F>
-    value_type accumulate(F && fold, value_type const & accum) const {
-      return std::accumulate(begin(), end(), accum, fold);
-    }
-
-    template <typename F, typename = std::enable_if_t<
-                              std::is_invocable_v<F, value_type, value_type>>>
-    std::optional<value_type> accumulate(F && fold) const {
-      if (empty()) { return std::nullopt; }
-      value_type first = *begin();
-      return std::accumulate(++begin(), end(), first, fold);
-    }
-
-    value_type accumulate(value_type const & accum) const {
-      return std::accumulate(begin(), end(), accum);
-    }
-
-    template <typename F> void each(F && consumer) const {
-      std::for_each(begin(), end(), consumer);
-    }
-
-    template <typename F>
-    stream_base<traits::mapped_t<T, F>> map(F && func) const &;
-    template <typename F> stream_base<T> filter(F && func) const &;
-    template <typename F>
-    stream_base<traits::fmapped_t<T, F>> flatmap(F && func) const &;
-
-    auto keys() const & {
-      return map([](auto & kv) -> decltype(auto) { return kv.first; });
-    }
-
-    auto values() const & {
-      return map([](auto & kv) -> decltype(auto) { return kv.second; });
-    }
-
-    template <typename F> stream_base<traits::mapped_t<T, F>> map(F && func) &&;
-    template <typename F> stream_base<T> filter(F && func) &&;
-    template <typename F>
-    stream_base<traits::fmapped_t<T, F>> flatmap(F && func) &&;
-
-    template <typename Cast> stream_base<Cast const &> cast() const & {
-      return map([](T const & p) -> Cast const & { return p; });
-    }
-
-    template <typename Cast> stream_base<Cast const &> cast() && {
-      return std::move(*this).map(
-          [](T const & p) -> Cast const & { return p; });
-    }
-
-    template <typename F, typename = traits::is_memvar_t<F>>
-    stream_base<traits::memvar_f<F>> map(F && memvar) const & {
-      return map(map_member_object<F>{memvar});
-    }
-
-    template <typename F, typename = traits::is_memfun_t<F>>
-    stream_base<traits::memfun_f<F>> map(F && memvar) const & {
-      return map(map_member_function<F>{memvar});
-    }
-
-    template <typename F, typename = traits::is_memvar_t<F>>
-    stream_base<traits::memvar_f<F>> map(F && memvar) && {
-      return std::move(*this).map(map_member_object<F>{memvar});
-    }
-
-    template <typename F, typename = traits::is_memfun_t<F>>
-    stream_base<traits::memfun_f<F>> map(F && memvar) && {
-      return std::move(*this).map(map_member_function<F>{memvar});
-    }
-
-  private:
-    iterator<T> (*do_begin)(std::shared_ptr<void>){nullptr};
-    iterator<T> (*do_end)(std::shared_ptr<void>){nullptr};
-    std::shared_ptr<void> impl_{nullptr};
-  };
+template <typename T, typename = void> class stream_base_pointer_impl {};
+
+template <typename T>
+class stream_base_pointer_impl<
+    T, std::enable_if_t<traits::is_dereferencable_v<T>>> {
+private:
+  using self_t = stream_base<T>;
+  using pointer = typename std::remove_reference<T>::type;
+  using element_type = typename std::pointer_traits<pointer>::element_type;
+
+public:
+  auto deref() const & -> stream_base<element_type &> {
+    return static_cast<self_t const *>(this)->map(
+        [](T const & p) -> element_type & { return *p; });
+  }
+
+  auto deref() && -> stream_base<element_type &> {
+    return static_cast<self_t &&>(*this).map(
+        [](T const & p) -> element_type & { return *p; });
+  }
+};
+
+template <typename T> class stream_base : public stream_base_pointer_impl<T> {
+private:
+  using value_type = typename std::decay<T>::type;
+
+public:
+  template <typename Stream> stream_base(std::shared_ptr<Stream> && impl) {
+    do_begin = [](std::shared_ptr<void> p) -> iterator<T> {
+      return std::static_pointer_cast<Stream>(p)->begin();
+    };
+    do_end = [](std::shared_ptr<void> p) -> iterator<T> {
+      return std::static_pointer_cast<Stream>(p)->end();
+    };
+    impl_ = std::static_pointer_cast<void>(impl);
+  }
+
+  ::stream::iterator<T> begin() const { return do_begin(impl_); }
+  ::stream::iterator<T> end() const { return do_end(impl_); }
+
+  bool empty() const { return begin() == end(); }
+
+  std::vector<value_type> collect() const {
+    std::vector<value_type> coll;
+    collect(coll);
+    return coll;
+  }
+
+  template <typename C, typename = std::enable_if_t<
+                            !std::is_void_v<typename C::value_type>>>
+  C & collect(C & coll) const {
+    std::copy(begin(), end(), std::inserter(coll, coll.end()));
+    return coll;
+  }
+
+  std::optional<value_type> first() const {
+    return begin() != end() ? std::optional(*begin()) : std::nullopt;
+  }
+
+  template <typename F> bool none(F && pred) const {
+    return std::none_of(begin(), end(), pred);
+  }
+
+  template <typename F> bool all(F && pred) const {
+    return std::all_of(begin(), end(), pred);
+  }
+
+  template <typename F> bool any(F && pred) const {
+    return std::any_of(begin(), end(), pred);
+  }
+
+  template <typename F>
+  value_type accumulate(F && fold, value_type const & accum) const {
+    return std::accumulate(begin(), end(), accum, fold);
+  }
+
+  template <typename F, typename = std::enable_if_t<
+                            std::is_invocable_v<F, value_type, value_type>>>
+  std::optional<value_type> accumulate(F && fold) const {
+    if (empty()) { return std::nullopt; }
+    value_type first = *begin();
+    return std::accumulate(++begin(), end(), first, fold);
+  }
+
+  value_type accumulate(value_type const & accum) const {
+    return std::accumulate(begin(), end(), accum);
+  }
+
+  template <typename F> void each(F && consumer) const {
+    std::for_each(begin(), end(), consumer);
+  }
+
+  template <typename F>
+  stream_base<traits::mapped_t<T, F>> map(F && func) const &;
+  template <typename F> stream_base<T> filter(F && func) const &;
+  template <typename F>
+  stream_base<traits::fmapped_t<T, F>> flatmap(F && func) const &;
+
+  auto keys() const & {
+    return map([](auto & kv) -> decltype(auto) { return kv.first; });
+  }
+
+  auto values() const & {
+    return map([](auto & kv) -> decltype(auto) { return kv.second; });
+  }
+
+  template <typename F> stream_base<traits::mapped_t<T, F>> map(F && func) &&;
+  template <typename F> stream_base<T> filter(F && func) &&;
+  template <typename F>
+  stream_base<traits::fmapped_t<T, F>> flatmap(F && func) &&;
+
+  template <typename Cast> stream_base<Cast const &> cast() const & {
+    return map([](T const & p) -> Cast const & { return p; });
+  }
+
+  template <typename Cast> stream_base<Cast const &> cast() && {
+    return std::move(*this).map([](T const & p) -> Cast const & { return p; });
+  }
+
+  template <typename F, typename = traits::is_memvar_t<F>>
+  stream_base<traits::memvar_f<F>> map(F && memvar) const & {
+    return map(map_member_object<F>{memvar});
+  }
+
+  template <typename F, typename = traits::is_memfun_t<F>>
+  stream_base<traits::memfun_f<F>> map(F && memvar) const & {
+    return map(map_member_function<F>{memvar});
+  }
+
+  template <typename F, typename = traits::is_memvar_t<F>>
+  stream_base<traits::memvar_f<F>> map(F && memvar) && {
+    return std::move(*this).map(map_member_object<F>{memvar});
+  }
+
+  template <typename F, typename = traits::is_memfun_t<F>>
+  stream_base<traits::memfun_f<F>> map(F && memvar) && {
+    return std::move(*this).map(map_member_function<F>{memvar});
+  }
+
+private:
+  iterator<T> (*do_begin)(std::shared_ptr<void>){nullptr};
+  iterator<T> (*do_end)(std::shared_ptr<void>){nullptr};
+  std::shared_ptr<void> impl_{nullptr};
+};
 }