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

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


The following commit(s) were added to refs/heads/master by this push:
     new 1a998fe  [gutil] update map-util to benefit from C++17
1a998fe is described below

commit 1a998fe71dcf174efd12244f4580111e29037bfc
Author: Alexey Serbin <[email protected]>
AuthorDate: Fri Feb 5 22:35:33 2021 -0800

    [gutil] update map-util to benefit from C++17
    
    This patch updates map-util to benefit from C++17 features such as
    try_emplace() and insert_or_assign() for dictionary containers: see
    [1], [2], [3], [4] for details.  At least, with try_emplace() a new
    element isn't ever constructed if the container already contains
    an element with the specified key.
    
    [1] https://en.cppreference.com/w/cpp/container/map/try_emplace
    [2] https://en.cppreference.com/w/cpp/container/map/insert_or_assign
    [3] https://en.cppreference.com/w/cpp/container/unordered_map/try_emplace
    [4] 
https://en.cppreference.com/w/cpp/container/unordered_map/insert_or_assign
    
    Change-Id: I248c03e604855434ea3a0891c311461a455b428e
    Reviewed-on: http://gerrit.cloudera.org:8080/17035
    Reviewed-by: Bankim Bhavsar <[email protected]>
    Tested-by: Kudu Jenkins
---
 src/kudu/gutil/map-util.h | 59 ++++++++++++++++++++++++++++-------------------
 1 file changed, 35 insertions(+), 24 deletions(-)

diff --git a/src/kudu/gutil/map-util.h b/src/kudu/gutil/map-util.h
index dc089b8..a0a5ea2 100644
--- a/src/kudu/gutil/map-util.h
+++ b/src/kudu/gutil/map-util.h
@@ -439,12 +439,30 @@ typename Collection::mapped_type& InsertKeyOrDie(
 //
 // Emplace*()
 //
+
+// Dancing with std::enable_if() is necessary to make these two functions
+// below work for both dictionary-like and set-like containers as well.
+// The idea is that for dictionary-like containers Collection::value_type
+// is always pair<const key_type, mapped_type>, so it cannot be the same
+// as key type.
 template <class Collection, class... Args>
-bool EmplaceIfNotPresent(Collection* const collection,
-                         Args&&... args) {
+typename std::enable_if<
+    std::is_same<typename Collection::key_type,
+                 typename Collection::value_type>::value,
+    bool>::type
+EmplaceIfNotPresent(Collection* const collection, Args&&... args) {
   return collection->emplace(std::forward<Args>(args)...).second;
 }
 
+template <class Collection, class... Args>
+typename std::enable_if<
+    !std::is_same<typename Collection::key_type,
+                  typename Collection::value_type>::value,
+    bool>::type
+EmplaceIfNotPresent(Collection* const collection, Args&&... args) {
+  return collection->try_emplace(std::forward<Args>(args)...).second;
+}
+
 // Emplaces the given key-value pair into the collection. Returns true if the
 // given key didn't previously exist. If the given key already existed in the
 // map, its value is changed to the given "value" and false is returned.
@@ -452,22 +470,15 @@ template <class Collection>
 bool EmplaceOrUpdate(Collection* const collection,
                      const typename Collection::key_type& key,
                      typename Collection::mapped_type&& value) {
-  typedef typename Collection::mapped_type mapped_type;
-  auto it = collection->find(key);
-  if (it == collection->end()) {
-    collection->emplace(key, std::forward<mapped_type>(value));
-    return true;
-  }
-  it->second = std::forward<mapped_type>(value);
-  return false;
+  return collection->insert_or_assign(
+      key, std::forward<typename Collection::mapped_type>(value)).second;
 }
 
-// EmplaceOrDie() returns reference to the mapped object for map-like 
containers
-// or constant reference to the element itself for set-like containers given
-// the key and parameters to construct the mapped object in-place (the latter
-// is only for map-like containers).
-// Dancing with std::enable_if() is necessary to make it work for set-like
-// containers as well.
+// Given the key and parameters to construct the mapped object in-place,
+// EmplaceOrDie() returns reference to the mapped object for dictionary-like
+// containers or constant reference to the element itself for set-like ones.
+// See the comment for EmplaceIfNotPresent() for details behind the template
+// meta-programming details.
 template <class Collection, class... Args>
 typename std::enable_if<
     std::is_same<typename Collection::key_type,
@@ -515,18 +526,18 @@ LookupOrInsert(Collection* const collection,
 }
 
 // It's similar to LookupOrInsert() but uses the emplace and r-value mechanics
-// to achieve the desired results. The constructor of the new element is called
-// with exactly the same arguments as supplied to emplace, forwarded via
-// std::forward<Args>(args). The element may be constructed even if there
-// already is an element with the same key in the container, in which case the
-// newly constructed element will be destroyed immediately.
+// to achieve the desired results, constructing the element in-place in the
+// container. The constructor of the new element is called with exactly the 
same
+// arguments as supplied to emplace, forwarded via std::forward<Args>(args).
+// The element is constructed only if there was no element with the specified
+// key in the container.
 // For details, see
-//   https://en.cppreference.com/w/cpp/container/map/emplace
-//   https://en.cppreference.com/w/cpp/container/unordered_map/emplace
+//   https://en.cppreference.com/w/cpp/container/map/try_emplace
+//   https://en.cppreference.com/w/cpp/container/unordered_map/try_emplace
 template <class Collection, class... Args>
 typename Collection::mapped_type&
 LookupOrEmplace(Collection* const collection, Args&&... args) {
-  return collection->emplace(std::forward<Args>(args)...).first->second;
+  return collection->try_emplace(std::forward<Args>(args)...).first->second;
 }
 
 // Counts the number of equivalent elements in the given "sequence", and stores

Reply via email to