Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(273)

Side by Side Diff: base/callback.h

Issue 2517793002: Improve compile error when invoking OnceCallback::Run on a non-rvalue. (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« base/bind_unittest.nc ('K') | « base/bind_unittest.nc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #ifndef BASE_CALLBACK_H_ 5 #ifndef BASE_CALLBACK_H_
6 #define BASE_CALLBACK_H_ 6 #define BASE_CALLBACK_H_
7 7
8 #include "base/callback_forward.h" 8 #include "base/callback_forward.h"
9 #include "base/callback_internal.h" 9 #include "base/callback_internal.h"
10 10
11 // NOTE: Header files that do not require the full definition of Callback or 11 // NOTE: Header files that do not require the full definition of Callback or
12 // Closure should #include "base/callback_forward.h" instead of this file. 12 // Closure should #include "base/callback_forward.h" instead of this file.
13 13
14 // ----------------------------------------------------------------------------- 14 // -----------------------------------------------------------------------------
15 // Usage documentation 15 // Usage documentation
16 // ----------------------------------------------------------------------------- 16 // -----------------------------------------------------------------------------
17 // 17 //
18 // See //docs/callback.md for documentation. 18 // See //docs/callback.md for documentation.
19 19
20 namespace base { 20 namespace base {
21 21
22 namespace internal { 22 namespace internal {
23 23
24 template <typename CallbackType>
25 struct IsOnceCallback : std::false_type {};
26
27 template <typename Signature>
28 struct IsOnceCallback<OnceCallback<Signature>> : std::true_type {};
29
24 // RunMixin provides different variants of `Run()` function to `Callback<>` 30 // RunMixin provides different variants of `Run()` function to `Callback<>`
25 // based on the type of callback. 31 // based on the type of callback.
26 template <typename CallbackType> 32 template <typename CallbackType>
27 class RunMixin; 33 class RunMixin;
28 34
29 // Specialization for OnceCallback. 35 // Specialization for OnceCallback.
30 template <typename R, typename... Args> 36 template <typename R, typename... Args>
31 class RunMixin<Callback<R(Args...), CopyMode::MoveOnly, RepeatMode::Once>> { 37 class RunMixin<OnceCallback<R(Args...)>> {
32 private: 38 private:
33 using CallbackType = 39 using CallbackType = OnceCallback<R(Args...)>;
34 Callback<R(Args...), CopyMode::MoveOnly, RepeatMode::Once>;
35 40
36 public: 41 public:
37 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...); 42 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
38 43
44 R Run(Args... args) & {
dcheng 2016/11/19 08:07:59 All overloads must either use ref-qualifiers or no
45 static_assert(!IsOnceCallback<CallbackType>::value,
dcheng 2016/11/19 08:07:59 This feels a bit silly, but we need to make sure t
vmpstr 2016/11/21 20:00:40 14.7.1 of the standard is so dense that I don't un
dcheng 2016/11/22 01:48:28 Added a language lawyering explanation; hopefully
46 "OnceCallback::Run() may only be invoked on an rvalue, i.e. "
47 "std::move(callback).Run().");
48 }
49
39 R Run(Args... args) && { 50 R Run(Args... args) && {
40 // Move the callback instance into a local variable before the invocation, 51 // Move the callback instance into a local variable before the invocation,
41 // that ensures the internal state is cleared after the invocation. 52 // that ensures the internal state is cleared after the invocation.
42 // It's not safe to touch |this| after the invocation, since running the 53 // It's not safe to touch |this| after the invocation, since running the
43 // bound function may destroy |this|. 54 // bound function may destroy |this|.
44 CallbackType cb = static_cast<CallbackType&&>(*this); 55 CallbackType cb = static_cast<CallbackType&&>(*this);
45 PolymorphicInvoke f = 56 PolymorphicInvoke f =
46 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke()); 57 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
47 return f(cb.bind_state_.get(), std::forward<Args>(args)...); 58 return f(cb.bind_state_.get(), std::forward<Args>(args)...);
48 } 59 }
49 }; 60 };
50 61
51 // Specialization for RepeatingCallback. 62 // Specialization for RepeatingCallback.
52 template <typename R, typename... Args, CopyMode copy_mode> 63 template <typename R, typename... Args>
53 class RunMixin<Callback<R(Args...), copy_mode, RepeatMode::Repeating>> { 64 class RunMixin<RepeatingCallback<R(Args...)>> {
54 private: 65 private:
55 using CallbackType = Callback<R(Args...), copy_mode, RepeatMode::Repeating>; 66 using CallbackType = RepeatingCallback<R(Args...)>;
56 67
57 public: 68 public:
58 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...); 69 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
59 70
60 R Run(Args... args) const { 71 R Run(Args... args) const {
61 const CallbackType& cb = static_cast<const CallbackType&>(*this); 72 const CallbackType& cb = static_cast<const CallbackType&>(*this);
62 PolymorphicInvoke f = 73 PolymorphicInvoke f =
63 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke()); 74 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
64 return f(cb.bind_state_.get(), std::forward<Args>(args)...); 75 return f(cb.bind_state_.get(), std::forward<Args>(args)...);
65 } 76 }
66 }; 77 };
67 78
68 template <typename From, typename To> 79 template <typename From, typename To>
69 struct IsCallbackConvertible : std::false_type {}; 80 struct IsCallbackConvertible : std::false_type {};
70 81
71 template <typename Signature> 82 template <typename Signature>
72 struct IsCallbackConvertible< 83 struct IsCallbackConvertible<RepeatingCallback<Signature>,
73 Callback<Signature, CopyMode::Copyable, RepeatMode::Repeating>, 84 OnceCallback<Signature>> : std::true_type {};
74 Callback<Signature, CopyMode::MoveOnly, RepeatMode::Once>> : std::true_type {
75 };
76 85
77 } // namespace internal 86 } // namespace internal
78 87
79 template <typename R, 88 template <typename R,
80 typename... Args, 89 typename... Args,
81 internal::CopyMode copy_mode, 90 internal::CopyMode copy_mode,
82 internal::RepeatMode repeat_mode> 91 internal::RepeatMode repeat_mode>
83 class Callback<R(Args...), copy_mode, repeat_mode> 92 class Callback<R(Args...), copy_mode, repeat_mode>
84 : public internal::CallbackBase<copy_mode>, 93 : public internal::CallbackBase<copy_mode>,
85 public internal::RunMixin<Callback<R(Args...), copy_mode, repeat_mode>> { 94 public internal::RunMixin<Callback<R(Args...), copy_mode, repeat_mode>> {
(...skipping 29 matching lines...) Expand all
115 bool Equals(const Callback& other) const { 124 bool Equals(const Callback& other) const {
116 return this->EqualsInternal(other); 125 return this->EqualsInternal(other);
117 } 126 }
118 127
119 friend class internal::RunMixin<Callback>; 128 friend class internal::RunMixin<Callback>;
120 }; 129 };
121 130
122 } // namespace base 131 } // namespace base
123 132
124 #endif // BASE_CALLBACK_H_ 133 #endif // BASE_CALLBACK_H_
OLDNEW
« base/bind_unittest.nc ('K') | « base/bind_unittest.nc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698