Add folly::Identity function object to Utility.h; replace AtomicHashArray's AHAIdenti...
authorEric Niebler <eniebler@fb.com>
Tue, 9 May 2017 21:30:11 +0000 (14:30 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Tue, 9 May 2017 21:36:54 +0000 (14:36 -0700)
Summary: Code duplication is bad.

Reviewed By: yfeldblum

Differential Revision: D5011806

fbshipit-source-id: cab7bb3af1c934a5a63cd3fb98aa33f2578aebfb

folly/AtomicHashArray.h
folly/Utility.h
folly/gen/Base.h

index 96a647d1a3da6bcf0e0f907273a20da1c09f7a24..e590dad5cdb38b2a882043bc87d0d1b84bfa0672 100644 (file)
@@ -39,6 +39,7 @@
 
 #include <folly/Hash.h>
 #include <folly/ThreadCachedInt.h>
 
 #include <folly/Hash.h>
 #include <folly/ThreadCachedInt.h>
+#include <folly/Utility.h>
 
 namespace folly {
 
 
 namespace folly {
 
@@ -66,16 +67,6 @@ struct AtomicHashArrayQuadraticProbeFcn
 
 // Enables specializing checkLegalKey without specializing its class.
 namespace detail {
 
 // Enables specializing checkLegalKey without specializing its class.
 namespace detail {
-// Local copy of folly::gen::Identity, to avoid heavy dependencies.
-class AHAIdentity {
- public:
-  template<class Value>
-  auto operator()(Value&& value) const ->
-    decltype(std::forward<Value>(value)) {
-    return std::forward<Value>(value);
-  }
-};
-
 template <typename NotKeyT, typename KeyT>
 inline void checkLegalKeyIfKeyTImpl(NotKeyT /* ignored */,
                                     KeyT /* emptyKey */,
 template <typename NotKeyT, typename KeyT>
 inline void checkLegalKeyIfKeyTImpl(NotKeyT /* ignored */,
                                     KeyT /* emptyKey */,
@@ -91,20 +82,24 @@ inline void checkLegalKeyIfKeyTImpl(KeyT key_in, KeyT emptyKey,
 }
 }  // namespace detail
 
 }
 }  // namespace detail
 
-template <class KeyT, class ValueT,
-          class HashFcn = std::hash<KeyT>,
-          class EqualFcn = std::equal_to<KeyT>,
-          class Allocator = std::allocator<char>,
-          class ProbeFcn = AtomicHashArrayLinearProbeFcn,
-          class KeyConvertFcn = detail::AHAIdentity>
+template <
+    class KeyT,
+    class ValueT,
+    class HashFcn = std::hash<KeyT>,
+    class EqualFcn = std::equal_to<KeyT>,
+    class Allocator = std::allocator<char>,
+    class ProbeFcn = AtomicHashArrayLinearProbeFcn,
+    class KeyConvertFcn = Identity>
 class AtomicHashMap;
 
 class AtomicHashMap;
 
-template <class KeyT, class ValueT,
-          class HashFcn = std::hash<KeyT>,
-          class EqualFcn = std::equal_to<KeyT>,
-          class Allocator = std::allocator<char>,
-          class ProbeFcn = AtomicHashArrayLinearProbeFcn,
-          class KeyConvertFcn = detail::AHAIdentity>
+template <
+    class KeyT,
+    class ValueT,
+    class HashFcn = std::hash<KeyT>,
+    class EqualFcn = std::equal_to<KeyT>,
+    class Allocator = std::allocator<char>,
+    class ProbeFcn = AtomicHashArrayLinearProbeFcn,
+    class KeyConvertFcn = Identity>
 class AtomicHashArray : boost::noncopyable {
   static_assert((std::is_convertible<KeyT,int32_t>::value ||
                  std::is_convertible<KeyT,int64_t>::value ||
 class AtomicHashArray : boost::noncopyable {
   static_assert((std::is_convertible<KeyT,int32_t>::value ||
                  std::is_convertible<KeyT,int64_t>::value ||
@@ -348,13 +343,12 @@ friend class AtomicHashMap<KeyT,
     SimpleRetT() = default;
   };
 
     SimpleRetT() = default;
   };
 
-
-
-  template <typename LookupKeyT = key_type,
-            typename LookupHashFcn = hasher,
-            typename LookupEqualFcn = key_equal,
-            typename LookupKeyToKeyFcn = detail::AHAIdentity,
-            typename... ArgTs>
+  template <
+      typename LookupKeyT = key_type,
+      typename LookupHashFcn = hasher,
+      typename LookupEqualFcn = key_equal,
+      typename LookupKeyToKeyFcn = Identity,
+      typename... ArgTs>
   SimpleRetT insertInternal(LookupKeyT key, ArgTs&&... vCtorArgs);
 
   template <typename LookupKeyT = key_type,
   SimpleRetT insertInternal(LookupKeyT key, ArgTs&&... vCtorArgs);
 
   template <typename LookupKeyT = key_type,
index f8f4f9bb07d5e5a94156f04f46f43637ed4b7098..4d6725d7070ec70e9684d19db915100c6fc5e9cc 100644 (file)
@@ -131,4 +131,31 @@ template <std::size_t N>
 using make_index_sequence = detail::make_index_sequence<N>;
 
 #endif
 using make_index_sequence = detail::make_index_sequence<N>;
 
 #endif
+
+/**
+ * A simple function object that passes its argument through unchanged.
+ *
+ * Example:
+ *
+ *   int i = 42;
+ *   int &j = Identity()(i);
+ *   assert(&i == &j);
+ *
+ * Warning: passing a prvalue through Identity turns it into an xvalue,
+ * which can effect whether lifetime extension occurs or not. For instance:
+ *
+ *   auto&& x = std::make_unique<int>(42);
+ *   cout << *x ; // OK, x refers to a valid unique_ptr.
+ *
+ *   auto&& y = Identity()(std::make_unique<int>(42));
+ *   cout << *y ; // ERROR: y did not lifetime-extend the unique_ptr. It
+ *                // is no longer valid
+ */
+struct Identity {
+  using is_transparent = void;
+  template <class T>
+  constexpr T&& operator()(T&& x) const noexcept {
+    return static_cast<T&&>(x);
+  }
+};
 }
 }
index 61e9d4104b383c0f0e968304e820ee456d1c6a92..a5d4b05a2e1166bd549dee6aa1908760f459b8f0 100644 (file)
@@ -30,6 +30,7 @@
 #include <folly/Conv.h>
 #include <folly/Optional.h>
 #include <folly/Range.h>
 #include <folly/Conv.h>
 #include <folly/Optional.h>
 #include <folly/Range.h>
+#include <folly/Utility.h>
 #include <folly/gen/Core.h>
 
 /**
 #include <folly/gen/Core.h>
 
 /**
@@ -199,15 +200,6 @@ public:
   }
 };
 
   }
 };
 
-class Identity {
-public:
-  template<class Value>
-  auto operator()(Value&& value) const ->
-  decltype(std::forward<Value>(value)) {
-    return std::forward<Value>(value);
-  }
-};
-
 /**
  * Class and helper function for negating a boolean Predicate
  */
 /**
  * Class and helper function for negating a boolean Predicate
  */