Move folly/Functional.h v2017.11.06.00
authorYedidya Feldblum <yfeldblum@fb.com>
Sun, 5 Nov 2017 04:34:13 +0000 (21:34 -0700)
committerFacebook Github Bot <facebook-github-bot@users.noreply.github.com>
Sun, 5 Nov 2017 04:46:40 +0000 (21:46 -0700)
Summary: [Folly] Move `folly/Functional.h` to `folly/lang/RValueReferenceWrapper.h`.

Reviewed By: Orvid

Differential Revision: D6242160

fbshipit-source-id: a8ec42106cfe0ea617c87d382694d5eb2f0f61a0

folly/Functional.h [deleted file]
folly/Makefile.am
folly/container/Iterator.h
folly/lang/RValueReferenceWrapper.h [new file with mode: 0644]
folly/lang/test/RValueReferenceWrapperTest.cpp [new file with mode: 0644]
folly/test/FunctionalTest.cpp [deleted file]
folly/test/Makefile.am

diff --git a/folly/Functional.h b/folly/Functional.h
deleted file mode 100644 (file)
index e239e1a..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2017-present Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <cassert>
-#include <memory>
-#include <utility>
-
-namespace folly {
-
-/**
- * Class template that wraps a reference to an rvalue. Similar to
- * std::reference_wrapper but with three important differences:
- *
- * 1) folly::rvalue_reference_wrappers can only be moved, not copied;
- * 2) the get() function and the conversion-to-T operator are destructive and
- *    not const, they invalidate the wrapper;
- * 3) the constructor-from-T is explicit.
- *
- * These restrictions are designed to make it harder to accidentally create a
- * a dangling rvalue reference, or to use an rvalue reference multiple times.
- * (Using an rvalue reference typically implies invalidation of the target
- * object, such as move-assignment to another object.)
- *
- * @seealso folly::rref
- */
-template <class T>
-class rvalue_reference_wrapper {
- public:
-  using type = T;
-
-  /**
-   * Default constructor. Creates an invalid reference. Must be move-assigned
-   * to in order to be come valid.
-   */
-  rvalue_reference_wrapper() noexcept : ptr_(nullptr) {}
-
-  /**
-   * Explicit constructor to make it harder to accidentally create a dangling
-   * reference to a temporary.
-   */
-  explicit rvalue_reference_wrapper(T&& ref) noexcept
-      : ptr_(std::addressof(ref)) {}
-
-  /**
-   * No construction from lvalue reference. Use std::move.
-   */
-  explicit rvalue_reference_wrapper(T&) noexcept = delete;
-
-  /**
-   * Destructive move construction.
-   */
-  rvalue_reference_wrapper(rvalue_reference_wrapper<T>&& other) noexcept
-      : ptr_(other.ptr_) {
-    other.ptr_ = nullptr;
-  }
-
-  /**
-   * Destructive move assignment.
-   */
-  rvalue_reference_wrapper& operator=(
-      rvalue_reference_wrapper&& other) noexcept {
-    ptr_ = other.ptr_;
-    other.ptr_ = nullptr;
-    return *this;
-  }
-
-  /**
-   * Implicit conversion to raw reference. Destructive.
-   */
-  /* implicit */ operator T &&() && noexcept {
-    return static_cast<rvalue_reference_wrapper&&>(*this).get();
-  }
-
-  /**
-   * Explicit unwrap. Destructive.
-   */
-  T&& get() && noexcept {
-    assert(valid());
-    T& ref = *ptr_;
-    ptr_ = nullptr;
-    return static_cast<T&&>(ref);
-  }
-
-  /**
-   * Calls the callable object to whom reference is stored. Only available if
-   * the wrapped reference points to a callable object. Destructive.
-   */
-  template <class... Args>
-  decltype(auto) operator()(Args&&... args) &&
-      noexcept(noexcept(std::declval<T>()(std::forward<Args>(args)...))) {
-    return static_cast<rvalue_reference_wrapper&&>(*this).get()(
-        std::forward<Args>(args)...);
-  }
-
-  /**
-   * Check whether wrapped reference is valid.
-   */
-  bool valid() const noexcept {
-    return ptr_ != nullptr;
-  }
-
- private:
-  // Disallow copy construction and copy assignment, to make it harder to
-  // accidentally use an rvalue reference multiple times.
-  rvalue_reference_wrapper(const rvalue_reference_wrapper&) = delete;
-  rvalue_reference_wrapper& operator=(const rvalue_reference_wrapper&) = delete;
-
-  T* ptr_;
-};
-
-/**
- * Create a folly::rvalue_reference_wrapper. Analogous to std::ref().
- *
- * Warning: folly::rvalue_reference_wrappers are potentially dangerous, because
- * they can easily be used to capture references to temporary values. Users must
- * ensure that the target object outlives the reference wrapper.
- *
- * @example
- *   class Object {};
- *   void f(Object&&);
- *   // BAD
- *   void g() {
- *     auto ref = folly::rref(Object{});  // create reference to temporary
- *     f(std::move(ref));                 // pass dangling reference
- *   }
- *   // GOOD
- *   void h() {
- *     Object o;
- *     auto ref = folly::rref(std::move(o));
- *     f(std::move(ref));
- *   }
- */
-template <typename T>
-rvalue_reference_wrapper<T> rref(T&& value) noexcept {
-  return rvalue_reference_wrapper<T>(std::move(value));
-}
-template <typename T>
-rvalue_reference_wrapper<T> rref(T&) noexcept = delete;
-} // namespace folly
index e1c0e4645d632debfe9f28c636d328e9fd9957d8..37f95d1c682fafbf89cc200aabc5db09df1bf28e 100644 (file)
@@ -314,6 +314,7 @@ nobase_follyinclude_HEADERS = \
        json.h \
        lang/Assume.h \
        lang/Launder.h \
+       lang/RValueReferenceWrapper.h \
        lang/SafeAssert.h \
        Lazy.h \
        LifoSem.h \
@@ -453,7 +454,6 @@ nobase_follyinclude_HEADERS = \
        Try.h \
        Unicode.h \
        Function.h \
-       Functional.h \
        UncaughtExceptions.h \
        Unit.h \
        Uri.h \
index 1c316950de697fa491646dcc0d36687b40b7ee49..7db1136e6718f59803ccaa48b6b51dad01b69985 100644 (file)
@@ -23,7 +23,7 @@
 #include <type_traits>
 #include <utility>
 
-#include <folly/Functional.h>
+#include <folly/lang/RValueReferenceWrapper.h>
 
 namespace folly {
 
diff --git a/folly/lang/RValueReferenceWrapper.h b/folly/lang/RValueReferenceWrapper.h
new file mode 100644 (file)
index 0000000..e239e1a
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2017-present Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <cassert>
+#include <memory>
+#include <utility>
+
+namespace folly {
+
+/**
+ * Class template that wraps a reference to an rvalue. Similar to
+ * std::reference_wrapper but with three important differences:
+ *
+ * 1) folly::rvalue_reference_wrappers can only be moved, not copied;
+ * 2) the get() function and the conversion-to-T operator are destructive and
+ *    not const, they invalidate the wrapper;
+ * 3) the constructor-from-T is explicit.
+ *
+ * These restrictions are designed to make it harder to accidentally create a
+ * a dangling rvalue reference, or to use an rvalue reference multiple times.
+ * (Using an rvalue reference typically implies invalidation of the target
+ * object, such as move-assignment to another object.)
+ *
+ * @seealso folly::rref
+ */
+template <class T>
+class rvalue_reference_wrapper {
+ public:
+  using type = T;
+
+  /**
+   * Default constructor. Creates an invalid reference. Must be move-assigned
+   * to in order to be come valid.
+   */
+  rvalue_reference_wrapper() noexcept : ptr_(nullptr) {}
+
+  /**
+   * Explicit constructor to make it harder to accidentally create a dangling
+   * reference to a temporary.
+   */
+  explicit rvalue_reference_wrapper(T&& ref) noexcept
+      : ptr_(std::addressof(ref)) {}
+
+  /**
+   * No construction from lvalue reference. Use std::move.
+   */
+  explicit rvalue_reference_wrapper(T&) noexcept = delete;
+
+  /**
+   * Destructive move construction.
+   */
+  rvalue_reference_wrapper(rvalue_reference_wrapper<T>&& other) noexcept
+      : ptr_(other.ptr_) {
+    other.ptr_ = nullptr;
+  }
+
+  /**
+   * Destructive move assignment.
+   */
+  rvalue_reference_wrapper& operator=(
+      rvalue_reference_wrapper&& other) noexcept {
+    ptr_ = other.ptr_;
+    other.ptr_ = nullptr;
+    return *this;
+  }
+
+  /**
+   * Implicit conversion to raw reference. Destructive.
+   */
+  /* implicit */ operator T &&() && noexcept {
+    return static_cast<rvalue_reference_wrapper&&>(*this).get();
+  }
+
+  /**
+   * Explicit unwrap. Destructive.
+   */
+  T&& get() && noexcept {
+    assert(valid());
+    T& ref = *ptr_;
+    ptr_ = nullptr;
+    return static_cast<T&&>(ref);
+  }
+
+  /**
+   * Calls the callable object to whom reference is stored. Only available if
+   * the wrapped reference points to a callable object. Destructive.
+   */
+  template <class... Args>
+  decltype(auto) operator()(Args&&... args) &&
+      noexcept(noexcept(std::declval<T>()(std::forward<Args>(args)...))) {
+    return static_cast<rvalue_reference_wrapper&&>(*this).get()(
+        std::forward<Args>(args)...);
+  }
+
+  /**
+   * Check whether wrapped reference is valid.
+   */
+  bool valid() const noexcept {
+    return ptr_ != nullptr;
+  }
+
+ private:
+  // Disallow copy construction and copy assignment, to make it harder to
+  // accidentally use an rvalue reference multiple times.
+  rvalue_reference_wrapper(const rvalue_reference_wrapper&) = delete;
+  rvalue_reference_wrapper& operator=(const rvalue_reference_wrapper&) = delete;
+
+  T* ptr_;
+};
+
+/**
+ * Create a folly::rvalue_reference_wrapper. Analogous to std::ref().
+ *
+ * Warning: folly::rvalue_reference_wrappers are potentially dangerous, because
+ * they can easily be used to capture references to temporary values. Users must
+ * ensure that the target object outlives the reference wrapper.
+ *
+ * @example
+ *   class Object {};
+ *   void f(Object&&);
+ *   // BAD
+ *   void g() {
+ *     auto ref = folly::rref(Object{});  // create reference to temporary
+ *     f(std::move(ref));                 // pass dangling reference
+ *   }
+ *   // GOOD
+ *   void h() {
+ *     Object o;
+ *     auto ref = folly::rref(std::move(o));
+ *     f(std::move(ref));
+ *   }
+ */
+template <typename T>
+rvalue_reference_wrapper<T> rref(T&& value) noexcept {
+  return rvalue_reference_wrapper<T>(std::move(value));
+}
+template <typename T>
+rvalue_reference_wrapper<T> rref(T&) noexcept = delete;
+} // namespace folly
diff --git a/folly/lang/test/RValueReferenceWrapperTest.cpp b/folly/lang/test/RValueReferenceWrapperTest.cpp
new file mode 100644 (file)
index 0000000..7f44aa7
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2017 Facebook, Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <utility>
+
+#include <folly/lang/RValueReferenceWrapper.h>
+#include <folly/portability/GTest.h>
+
+TEST(RvalueReferenceWrapper, MoveAndConvert) {
+  using folly::rvalue_reference_wrapper;
+
+  // Destructive moves.
+  int i1 = 0;
+  rvalue_reference_wrapper<int> rref1(std::move(i1));
+  ASSERT_TRUE(rref1.valid());
+  rvalue_reference_wrapper<int> rref0(std::move(rref1));
+  ASSERT_TRUE(rref0.valid());
+  ASSERT_FALSE(rref1.valid());
+  rref1 = std::move(rref0);
+  ASSERT_FALSE(rref0.valid());
+  ASSERT_TRUE(rref1.valid());
+  const int& r1 = std::move(rref1);
+  ASSERT_FALSE(rref1.valid());
+  ASSERT_EQ(&r1, &i1);
+
+  // Destructive unwrap to T&&.
+  int i2 = 0;
+  rvalue_reference_wrapper<int> rref2(std::move(i2));
+  int&& r2 = std::move(rref2);
+  ASSERT_EQ(&r2, &i2);
+
+  // Destructive unwrap to const T&.
+  const int i3 = 0;
+  rvalue_reference_wrapper<const int> rref3(std::move(i3));
+  const int& r3 = std::move(rref3);
+  ASSERT_EQ(&r3, &i3);
+
+  // Destructive unwrap to const T&&.
+  const int i4 = 0;
+  rvalue_reference_wrapper<const int> rref4(std::move(i4));
+  const int&& r4 = std::move(rref4);
+  ASSERT_EQ(&r4, &i4);
+
+  /*
+   * Things that intentionally do not compile. Copy construction, copy
+   * assignment, unwrap of lvalue reference to wrapper, const violations.
+   *
+  int i5;
+  const int i6 = 0;
+  rvalue_reference_wrapper<int> rref5(i5);
+  rvalue_reference_wrapper<const int> rref6(i6);
+  rref1 = rref5;
+  int& r5 = rref5;
+  const int& r6 = rref6;
+  int i7;
+  const rvalue_reference_wrapper<int> rref7(std::move(i7));
+  int& r7 = std::move(rref7);
+  */
+}
+
+TEST(RvalueReferenceWrapper, Call) {
+  int a = 4711, b, c;
+  auto callMe = [&](int x, const int& y, int&& z) -> int {
+    EXPECT_EQ(a, x);
+    EXPECT_EQ(&b, &y);
+    EXPECT_EQ(&c, &z);
+    return a;
+  };
+  int result = folly::rref(std::move(callMe))(a, b, std::move(c));
+  EXPECT_EQ(a, result);
+}
diff --git a/folly/test/FunctionalTest.cpp b/folly/test/FunctionalTest.cpp
deleted file mode 100644 (file)
index f8a81f1..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2017 Facebook, Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *   http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <utility>
-
-#include <folly/Functional.h>
-#include <folly/portability/GTest.h>
-
-TEST(RvalueReferenceWrapper, MoveAndConvert) {
-  using folly::rvalue_reference_wrapper;
-
-  // Destructive moves.
-  int i1 = 0;
-  rvalue_reference_wrapper<int> rref1(std::move(i1));
-  ASSERT_TRUE(rref1.valid());
-  rvalue_reference_wrapper<int> rref0(std::move(rref1));
-  ASSERT_TRUE(rref0.valid());
-  ASSERT_FALSE(rref1.valid());
-  rref1 = std::move(rref0);
-  ASSERT_FALSE(rref0.valid());
-  ASSERT_TRUE(rref1.valid());
-  const int& r1 = std::move(rref1);
-  ASSERT_FALSE(rref1.valid());
-  ASSERT_EQ(&r1, &i1);
-
-  // Destructive unwrap to T&&.
-  int i2 = 0;
-  rvalue_reference_wrapper<int> rref2(std::move(i2));
-  int&& r2 = std::move(rref2);
-  ASSERT_EQ(&r2, &i2);
-
-  // Destructive unwrap to const T&.
-  const int i3 = 0;
-  rvalue_reference_wrapper<const int> rref3(std::move(i3));
-  const int& r3 = std::move(rref3);
-  ASSERT_EQ(&r3, &i3);
-
-  // Destructive unwrap to const T&&.
-  const int i4 = 0;
-  rvalue_reference_wrapper<const int> rref4(std::move(i4));
-  const int&& r4 = std::move(rref4);
-  ASSERT_EQ(&r4, &i4);
-
-  /*
-   * Things that intentionally do not compile. Copy construction, copy
-   * assignment, unwrap of lvalue reference to wrapper, const violations.
-   *
-  int i5;
-  const int i6 = 0;
-  rvalue_reference_wrapper<int> rref5(i5);
-  rvalue_reference_wrapper<const int> rref6(i6);
-  rref1 = rref5;
-  int& r5 = rref5;
-  const int& r6 = rref6;
-  int i7;
-  const rvalue_reference_wrapper<int> rref7(std::move(i7));
-  int& r7 = std::move(rref7);
-  */
-}
-
-TEST(RvalueReferenceWrapper, Call) {
-  int a = 4711, b, c;
-  auto callMe = [&](int x, const int& y, int&& z) -> int {
-    EXPECT_EQ(a, x);
-    EXPECT_EQ(&b, &y);
-    EXPECT_EQ(&c, &z);
-    return a;
-  };
-  int result = folly::rref(std::move(callMe))(a, b, std::move(c));
-  EXPECT_EQ(a, result);
-}
index e5da501036cc64887e3a0c35b3e6f0b1d67ed881..4bf6b29db8bbb32f6dd76d48a3b9b6f5c3dad990 100644 (file)
@@ -328,10 +328,10 @@ function_test_SOURCES = \
 function_test_LDADD = libfollytestmain.la
 TESTS += function_test
 
-functional_test_SOURCES = \
-               FunctionalTest.cpp
-functional_test_LDADD = libfollytestmain.la
-TESTS += functional_test
+rvalue_reference_wrapper_test_SOURCES = \
+               ../lang/RValueReferenceWrapperTest.cpp
+rvalue_reference_wrapper_test_LDADD = libfollytestmain.la
+TESTS += rvalue_reference_wrapper_test
 
 ssl_test_SOURCES = \
                ../ssl/test/OpenSSLHashTest.cpp