1 | // Copyright 2013 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | #ifndef FLUTTER_FML_MAKE_COPYABLE_H_ |
6 | #define FLUTTER_FML_MAKE_COPYABLE_H_ |
7 | |
8 | #include <utility> |
9 | |
10 | #include "flutter/fml/memory/ref_counted.h" |
11 | #include "flutter/fml/memory/ref_ptr.h" |
12 | |
13 | namespace fml { |
14 | namespace internal { |
15 | |
16 | template <typename T> |
17 | class CopyableLambda { |
18 | public: |
19 | explicit CopyableLambda(T func) |
20 | : impl_(MakeRefCounted<Impl>(std::move(func))) {} |
21 | |
22 | template <typename... ArgType> |
23 | auto operator()(ArgType&&... args) const { |
24 | return impl_->func_(std::forward<ArgType>(args)...); |
25 | } |
26 | |
27 | private: |
28 | class Impl : public RefCountedThreadSafe<Impl> { |
29 | public: |
30 | explicit Impl(T func) : func_(std::move(func)) {} |
31 | T func_; |
32 | }; |
33 | |
34 | RefPtr<Impl> impl_; |
35 | }; |
36 | |
37 | } // namespace internal |
38 | |
39 | // Provides a wrapper for a move-only lambda that is implictly convertable to an |
40 | // std::function. |
41 | // |
42 | // std::function is copyable, but if a lambda captures an argument with a |
43 | // move-only type, the lambda itself is not copyable. In order to use the lambda |
44 | // in places that accept std::functions, we provide a copyable object that wraps |
45 | // the lambda and is implicitly convertable to an std::function. |
46 | // |
47 | // EXAMPLE: |
48 | // |
49 | // std::unique_ptr<Foo> foo = ... |
50 | // std::function<int()> func = |
51 | // fml::MakeCopyable([bar = std::move(foo)]() { return bar->count(); }); |
52 | // |
53 | // Notice that the return type of MakeCopyable is rarely used directly. Instead, |
54 | // callers typically erase the type by implicitly converting the return value |
55 | // to an std::function. |
56 | template <typename T> |
57 | internal::CopyableLambda<T> MakeCopyable(T lambda) { |
58 | return internal::CopyableLambda<T>(std::move(lambda)); |
59 | } |
60 | |
61 | } // namespace fml |
62 | |
63 | #endif // FLUTTER_FML_MAKE_COPYABLE_H_ |
64 | |