This is an automated email from the ASF dual-hosted git repository.

amc pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit 46de4252f38b7df32943a702dc93dce79c3eb08e
Author: Alan M. Carroll <[email protected]>
AuthorDate: Fri Jul 20 08:36:45 2018 -0500

    IntrusiveHashMap: Add overloads to apply method to support functor taking 
reference or pointer.
---
 lib/ts/IntrusiveHashMap.h                  | 37 +++++++++++++++++++++++++-----
 lib/ts/unit-tests/test_IntrusiveHashMap.cc |  2 +-
 2 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/lib/ts/IntrusiveHashMap.h b/lib/ts/IntrusiveHashMap.h
index 003326b..3f1848a 100644
--- a/lib/ts/IntrusiveHashMap.h
+++ b/lib/ts/IntrusiveHashMap.h
@@ -617,17 +617,42 @@ IntrusiveHashMap<H>::erase(range const &r) -> iterator
   return this->erase(r.first, r.second);
 }
 
+namespace detail
+{
+// Make @c apply more convenient by allowing the function to take a reference 
type or pointer type to the container
+// elements. The pointer type is the base, plus a shim to convert from a 
reference type functor to a pointer pointer
+// type. The complex return type definition forces only one, but not both, to 
be valid for a particular functor. This
+// also must be done via free functions and not method overloads because the 
compiler forces a match up of method
+// definitions and declarations before any template instantiation.
+
+template <typename H, typename F>
+auto
+IntrusiveHashMapApply(IntrusiveHashMap<H> &map, F &&f)
+  -> decltype(f(*static_cast<typename IntrusiveHashMap<H>::value_type 
*>(nullptr)), map)
+{
+  return map.apply([&f](typename IntrusiveHashMap<H>::value_type *v) { return 
f(*v); });
+}
+
+template <typename H, typename F>
+auto
+IntrusiveHashMapApply(IntrusiveHashMap<H> &map, F &&f)
+  -> decltype(f(static_cast<typename IntrusiveHashMap<H>::value_type 
*>(nullptr)), map)
+{
+  auto spot{map.begin()};
+  auto limit{map.end()};
+  while (spot != limit) {
+    f(spot++); // post increment means @a spot is updated before @a f is 
applied.
+  }
+  return map;
+}
+} // namespace detail
+
 template <typename H>
 template <typename F>
 auto
 IntrusiveHashMap<H>::apply(F &&f) -> self_type &
 {
-  iterator spot{this->begin()};
-  iterator limit{this->end()};
-  while (spot != limit) {
-    f(*spot++); // post increment means @a spot is updated before @a f is 
applied.
-  }
-  return *this;
+  return detail::IntrusiveHashMapApply(*this, f);
 };
 
 template <typename H>
diff --git a/lib/ts/unit-tests/test_IntrusiveHashMap.cc 
b/lib/ts/unit-tests/test_IntrusiveHashMap.cc
index 6828e3a..abcbd35 100644
--- a/lib/ts/unit-tests/test_IntrusiveHashMap.cc
+++ b/lib/ts/unit-tests/test_IntrusiveHashMap.cc
@@ -144,5 +144,5 @@ TEST_CASE("IntrusiveHashMap", "[libts][IntrusiveHashMap]")
     REQUIRE(elt._payload == "dup"sv);
   }
   // clean up the last bits.
-  map.apply([](Thing &thing) { delete &thing; });
+  map.apply([](Thing *thing) { delete thing; });
 };

Reply via email to