Browse Source

Increasing const-correctness by adding && versions of appropriate transforms.
Marking terminating functions const that weren't already.

Adding a few helper typedefs.

Samuel Jaffe 8 years ago
parent
commit
199aab1ae4
4 changed files with 75 additions and 25 deletions
  1. 7 1
      streams/filter.hpp
  2. 8 2
      streams/join.hpp
  3. 7 1
      streams/map.hpp
  4. 53 21
      streams/streams.hpp

+ 7 - 1
streams/filter.hpp

@@ -54,7 +54,13 @@ namespace stream { namespace detail {
   
   template <typename T>
   template <typename F>
-  auto stream_base<T>::filter(F&& pred) const -> stream_base<T>  {
+  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);
   }
 } }

+ 8 - 2
streams/join.hpp

@@ -94,7 +94,13 @@ namespace stream { namespace detail {
   
   template <typename T>
   template <typename F>
-  auto stream_base<T>::flatmap(F&& func) const -> stream_base<flatmap_f<F>>  {
-    return make_join((*this).map(func));
+  auto stream_base<T>::flatmap(F&& func) && -> stream_base<flatmap_f<F>>  {
+    return make_join(std::move(*this).map(func));
+  }
+  
+  template <typename T>
+  template <typename F>
+  auto stream_base<T>::flatmap(F&& func) const & -> stream_base<flatmap_f<F>>  {
+    return make_join(map(func));
   }
 } }

+ 7 - 1
streams/map.hpp

@@ -36,7 +36,13 @@ namespace stream { namespace detail {
   
   template <typename T>
   template <typename F>
-  auto stream_base<T>::map(F&& func) const -> stream_base<map_f<F>> {
+  auto stream_base<T>::map(F&& func) && -> stream_base<map_f<F>> {
+    return std::make_shared<map_stream<T, map_f<F>>>(func, std::move(*this));
+  }
+  
+  template <typename T>
+  template <typename F>
+  auto stream_base<T>::map(F&& func) const & -> stream_base<map_f<F>> {
     return std::make_shared<map_stream<T, map_f<F>>>(func, *this);
   }
 } }

+ 53 - 21
streams/streams.hpp

@@ -107,11 +107,15 @@ namespace stream {
       using noref = typename std::remove_reference<T>::type;
       using element_type = typename std::pointer_traits<noref>::element_type;
     public:
-      auto deref() const -> stream_base<element_type &> {
+      auto deref() const & -> stream_base<element_type &> {
         return static_cast<stream_base<T> const *>(this)->map([](T const & p) -> element_type & { return *p; });
       }
+      
+      auto deref() && -> stream_base<element_type &> {
+        return static_cast<stream_base<T> &&>(*this).map([](T const & p) -> element_type & { return *p; });
+      }
     };
-
+    
     template <typename T>
     class stream_base : public stream_base_pointer_impl<T> {
     private:
@@ -119,6 +123,14 @@ namespace stream {
       using map_f = decltype(std::declval<F>()(std::declval<T>()));
       template <typename F>
       using flatmap_f = typename decltype(std::declval<F>()(std::declval<T>()))::value_type;
+      template <typename F>
+      using memvar_f = typename map_member_object<F>::type;
+      template <typename F>
+      using memfun_f = typename map_member_function<F>::type;
+      template <typename F>
+      using is_memvar = std::is_member_object_pointer<F>;
+      template <typename F>
+      using is_memfun = std::is_member_function_pointer<F>;
 
       using self = stream_base<T>;
       using noref = typename std::remove_reference<T>::type;
@@ -149,42 +161,62 @@ namespace stream {
       }
       
       template <typename F>
-      clean accumulate(F&& fold, clean const& accum) {
+      clean accumulate(F&& fold, clean const& accum) const {
         return std::accumulate(begin(), end(), accum, fold);
       }
       
-      clean accumulate(clean const& accum) {
+      clean accumulate(clean const& accum) const {
         return std::accumulate(begin(), end(), accum);
       }
       
       template <typename F>
-      void each(F && consumer) {
+      void each(F && consumer) const {
         std::for_each(begin(), end(), consumer);
       }
       
       template <typename F>
-      stream_base<map_f<F>> map(F&& func) const;
-
-      template <typename F, typename = typename std::enable_if<std::is_member_object_pointer<F>::value>::type>
-      auto map(F && memvar) const -> stream_base<typename map_member_object<F>::type> {
+      stream_base<map_f<F>> map(F&& func) const &;
+      template <typename F>
+      stream_base<T> filter(F&& func) const &;
+      template <typename F>
+      stream_base<flatmap_f<F>> flatmap(F&& func) const &;
+      
+      template <typename F>
+      stream_base<map_f<F>> map(F&& func) &&;
+      template <typename F>
+      stream_base<T> filter(F&& func) &&;
+      template <typename F>
+      stream_base<flatmap_f<F>> flatmap(F&& func) &&;
+      
+      template <typename Cast>
+      auto cast() const & -> stream_base<Cast const &> {
+        return map([](T const & p) -> Cast const & { return p; });
+      }
+      
+      template <typename Cast>
+      auto cast() && -> stream_base<Cast const &> {
+        return std::move(*this).map([](T const & p) -> Cast const & { return p; });
+      }
+      
+      template <typename F, typename = typename std::enable_if<is_memvar<F>::value>::type>
+      auto map(F && memvar) const & -> stream_base<memvar_f<F>> {
         return map(map_member_object<F>{memvar});
       }
-
-      template <typename F, typename = typename std::enable_if<std::is_member_function_pointer<F>::value>::type>
-      auto map(F && memvar) const -> stream_base<typename map_member_function<F>::type> {
+      
+      template <typename F, typename = typename std::enable_if<is_memfun<F>::value>::type>
+      auto map(F && memvar) const & -> stream_base<memfun_f<F>> {
         return map(map_member_function<F>{memvar});
       }
-      
-      template <typename Cast>
-      auto cast() const -> stream_base<Cast const &> {
-        return map([](T const & p) -> Cast const & { return p; });
+
+      template <typename F, typename = typename std::enable_if<is_memvar<F>::value>::type>
+      auto map(F && memvar) && -> stream_base<memvar_f<F>> {
+        return std::move(*this).map(map_member_object<F>{memvar});
       }
 
-      template <typename F>
-      stream_base<T> filter(F&& func) const;
-      
-      template <typename F>
-      stream_base<flatmap_f<F>> flatmap(F&& func) const;
+      template <typename F, typename = typename std::enable_if<is_memfun<F>::value>::type>
+      auto map(F && memvar) && -> stream_base<memfun_f<F>> {
+        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};