+++ /dev/null
-/*
- * 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
json.h \
lang/Assume.h \
lang/Launder.h \
+ lang/RValueReferenceWrapper.h \
lang/SafeAssert.h \
Lazy.h \
LifoSem.h \
Try.h \
Unicode.h \
Function.h \
- Functional.h \
UncaughtExceptions.h \
Unit.h \
Uri.h \
#include <type_traits>
#include <utility>
-#include <folly/Functional.h>
+#include <folly/lang/RValueReferenceWrapper.h>
namespace folly {
--- /dev/null
+/*
+ * 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
--- /dev/null
+/*
+ * 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);
+}
+++ /dev/null
-/*
- * 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);
-}
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