2 * Copyright 2017-present Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
26 * Class template that wraps a reference to an rvalue. Similar to
27 * std::reference_wrapper but with three important differences:
29 * 1) folly::rvalue_reference_wrappers can only be moved, not copied;
30 * 2) the get() function and the conversion-to-T operator are destructive and
31 * not const, they invalidate the wrapper;
32 * 3) the constructor-from-T is explicit.
34 * These restrictions are designed to make it harder to accidentally create a
35 * a dangling rvalue reference, or to use an rvalue reference multiple times.
36 * (Using an rvalue reference typically implies invalidation of the target
37 * object, such as move-assignment to another object.)
39 * @seealso folly::rref
42 class rvalue_reference_wrapper {
47 * Default constructor. Creates an invalid reference. Must be move-assigned
48 * to in order to be come valid.
50 rvalue_reference_wrapper() noexcept : ptr_(nullptr) {}
53 * Explicit constructor to make it harder to accidentally create a dangling
54 * reference to a temporary.
56 explicit rvalue_reference_wrapper(T&& ref) noexcept
57 : ptr_(std::addressof(ref)) {}
60 * No construction from lvalue reference. Use std::move.
62 explicit rvalue_reference_wrapper(T&) noexcept = delete;
65 * Destructive move construction.
67 rvalue_reference_wrapper(rvalue_reference_wrapper<T>&& other) noexcept
73 * Destructive move assignment.
75 rvalue_reference_wrapper& operator=(
76 rvalue_reference_wrapper&& other) noexcept {
83 * Implicit conversion to raw reference. Destructive.
85 /* implicit */ operator T &&() && noexcept {
86 return static_cast<rvalue_reference_wrapper&&>(*this).get();
90 * Explicit unwrap. Destructive.
92 T&& get() && noexcept {
96 return static_cast<T&&>(ref);
100 * Calls the callable object to whom reference is stored. Only available if
101 * the wrapped reference points to a callable object. Destructive.
103 template <class... Args>
104 decltype(auto) operator()(Args&&... args) &&
105 noexcept(noexcept(std::declval<T>()(std::forward<Args>(args)...))) {
106 return static_cast<rvalue_reference_wrapper&&>(*this).get()(
107 std::forward<Args>(args)...);
111 * Check whether wrapped reference is valid.
113 bool valid() const noexcept {
114 return ptr_ != nullptr;
118 // Disallow copy construction and copy assignment, to make it harder to
119 // accidentally use an rvalue reference multiple times.
120 rvalue_reference_wrapper(const rvalue_reference_wrapper&) = delete;
121 rvalue_reference_wrapper& operator=(const rvalue_reference_wrapper&) = delete;
127 * Create a folly::rvalue_reference_wrapper. Analogous to std::ref().
129 * Warning: folly::rvalue_reference_wrappers are potentially dangerous, because
130 * they can easily be used to capture references to temporary values. Users must
131 * ensure that the target object outlives the reference wrapper.
138 * auto ref = folly::rref(Object{}); // create reference to temporary
139 * f(std::move(ref)); // pass dangling reference
144 * auto ref = folly::rref(std::move(o));
148 template <typename T>
149 rvalue_reference_wrapper<T> rref(T&& value) noexcept {
150 return rvalue_reference_wrapper<T>(std::move(value));
152 template <typename T>
153 rvalue_reference_wrapper<T> rref(T&) noexcept = delete;