[iter] hb_reduce, accumulator with a different type
authorEbrahim Byagowi <ebrahim@gnu.org>
Mon, 1 Apr 2019 20:00:06 +0000 (00:30 +0430)
committerBehdad Esfahbod <behdad@behdad.org>
Mon, 1 Apr 2019 23:56:29 +0000 (16:56 -0700)
src/hb-iter.hh
src/test-iter.cc

index 04261bd..f23904c 100644 (file)
@@ -348,31 +348,33 @@ static const struct
   { return hb_filter_iter_factory_t<Pred, Proj> (p, f); }
 } hb_filter HB_UNUSED;
 
-template <typename Redu, typename TValue>
+template <typename Redu, typename InitT>
 struct hb_reduce_t
 {
-  hb_reduce_t (Redu r, TValue init_value) : r (r), init_value (init_value) {}
+  hb_reduce_t (Redu r, InitT init_value) : r (r), init_value (init_value) {}
 
   template <typename Iter,
-           hb_enable_if (hb_is_iterator (Iter))>
-  TValue
+           hb_enable_if (hb_is_iterator (Iter)),
+           typename AccuT = decltype (hb_declval (Redu) (hb_declval (InitT), hb_declval (typename Iter::item_t)))>
+  AccuT
   operator () (Iter it) const
   {
-    TValue value = init_value;
+    AccuT value = init_value;
     for (; it; ++it)
-      value = r (*it, value);
+      value = r (value, *it);
     return value;
   }
 
   private:
   Redu r;
-  TValue init_value;
+  InitT init_value;
 };
 static const struct
 {
-  template <typename Redu, typename TValue> hb_reduce_t<Redu, TValue>
-  operator () (Redu&& r, TValue init_value) const
-  { return hb_reduce_t<Redu, TValue> (r, init_value); }
+  template <typename Redu, typename InitT>
+  hb_reduce_t<Redu, InitT>
+  operator () (Redu&& r, InitT init_value) const
+  { return hb_reduce_t<Redu, InitT> (r, init_value); }
 } hb_reduce HB_UNUSED;
 
 
index e142c56..071edab 100644 (file)
@@ -156,9 +156,33 @@ main (int argc, char **argv)
 
   + hb_iter (src)
   | hb_map ([&] (int i) -> int { return 1; })
-  | hb_reduce ([&] (int acc, int cur) -> int { return acc + cur; }, 2)
+  | hb_reduce ([&] (int acc, int value) -> int { return acc; }, 2)
   ;
 
+  unsigned int temp1 = 10;
+  unsigned int temp2 = 0;
+  hb_map_t *result =
+  + hb_iter (src)
+  | hb_map ([&] (int i) -> hb_set_t *
+           {
+             hb_set_t *set = hb_set_create ();
+             for (unsigned int i = 0; i < temp1; ++i)
+               hb_set_add (set, i);
+             temp1++;
+             return set;
+           })
+  | hb_reduce ([&] (hb_map_t *acc, hb_set_t *value) -> hb_map_t *
+              {
+                hb_map_set (acc, temp2++, hb_set_get_population (value));
+                // This is not a memory managed language, take care!
+                hb_set_destroy (value);
+                return acc;
+              }, hb_map_create ())
+  ;
+  // The result should be something like 0->10, 1->11, ..., 9->19
+  assert (hb_map_get (result, 9) == 19);
+  hb_map_destroy (result);
+
   + hb_iter (src)
   | hb_drain
   ;