jiuyiUniapp/service/node_modules/react-native/ReactCommon/cxxreact/MoveWrapper.h

126 lines
4.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include <memory>
namespace facebook::react {
/*
NOTE: we keep this internal copy of folly/MoveWrapper.h to unblock
the the workstream of dropping the dependency on folly in RN!
For a technical explanation on why we still need this we defer
to the doc in folly/Function.h:
"There are some limitations in std::function that folly::Function tries to
avoid. std::function is copy-constructible and requires that the callable that
it wraps is copy-constructible as well, which is a constraint that is often
inconvenient. In most cases when using a std::function you don't make use of
its copy-constructibility, so you might sometimes feel like you get back very
little in return for a noticeable restriction. This restriction becomes
apparent when trying to use a lambda capturing a unique_ptr (or any
non-copyable type) as a callback for a folly::Future.
std::unique_ptr<Foo> foo_ptr = new Foo;
some_future.then(
[foo_ptr = std::move(foo_ptr)] mutable
(int x)
{ foo_ptr->setX(x); }
);
This piece of code did not compile before folly::Future started using
folly::Function instead of std::function to store the callback. Because the
lambda captures something non-copyable (the unique_ptr), it is not copyable
itself. And std::function can only store copyable callables.
The implementation of folly::Future did not make use of the
copy-constructibility of std::function at any point. There was no benefit from
the fact that the std::function is copy-constructible, but the fact that it can
only wrap copy-constructible callables posed a restriction.
A workaround was available: folly::MoveWrapper, which wraps an object that may
be non-copyable and implements copy operations by moving the embedded object.
Using a folly::MoveWrapper, you can capture non-copyable objects in a lambda,
and the lambda itself is still copyable and may be wrapped in a std::function.
It is a pragmatic solution for the above problem, but you have to be a little
careful. The problem is that you cant use a MoveWrapper anywhere where copy
operations are assumed to behave like actual copy operations. Also, a
folly::MoveWrapper<std::unique_ptr<T>> essentially behaves like auto_ptr<T>. Ask
yourself whether youd want to use lots of auto_ptrs in your codebase. And the
original question still persists: we very often dont benefit from
copy-constructibility of std::function, so why do we have to live with this
restriction? I.e. why do we have to use MoveWrapper?"
*/
/** C++11 closures don't support move-in capture. Nor does std::bind.
facepalm.
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3610.html
"[...] a work-around that should make people's stomach crawl:
write a wrapper that performs move-on-copy, much like the deprecated
auto_ptr"
Unlike auto_ptr, this doesn't require a heap allocation.
*/
template <class T>
class MoveWrapper {
public:
/** If value can be default-constructed, why not?
Then we don't have to move it in */
MoveWrapper() = default;
/// Move a value in.
explicit MoveWrapper(T&& t) : value(std::move(t)) {}
/// copy is move
MoveWrapper(const MoveWrapper& other) : value(std::move(other.value)) {}
/// move is also move
MoveWrapper(MoveWrapper&& other) noexcept : value(std::move(other.value)) {}
const T& operator*() const {
return value;
}
T& operator*() {
return value;
}
const T* operator->() const {
return &value;
}
T* operator->() {
return &value;
}
/// move the value out (sugar for std::move(*moveWrapper))
T&& move() {
return std::move(value);
}
// If you want these you're probably doing it wrong, though they'd be
// easy enough to implement
MoveWrapper& operator=(const MoveWrapper&) = delete;
MoveWrapper& operator=(MoveWrapper&&) = delete;
private:
mutable T value;
};
/// Make a MoveWrapper from the argument. Because the name "makeMoveWrapper"
/// is already quite transparent in its intent, this will work for lvalues as
/// if you had wrapped them in std::move.
template <class T, class T0 = typename std::remove_reference<T>::type>
MoveWrapper<T0> makeMoveWrapper(T&& t) {
return MoveWrapper<T0>(std::forward<T0>(t));
}
} // namespace facebook::react