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

Side by Side Diff: base/callback.h

Issue 2517793002: Improve compile error when invoking OnceCallback::Run on a non-rvalue. (Closed)
Patch Set: Add C++ language lawyering explanation. 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
« no previous file with comments | « 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) & {
45 // Note: even though this static_assert will trivially always fail, it
46 // cannot be simply replaced with static_assert(false, ...) because:
47 // - Per [dcl.dcl]/p4, a program is ill-formed if the constant-expression
48 // argument does not evaluate to true.
49 // - Per [temp.res]/p8, if no valid specialization can be generated for a
50 // template definition, and that template is not instantiated, the
51 // template definition is ill-formed, no diagnostic required.
52 // These two clauses, taken together, would allow a conforming C++ compiler
53 // to immediately reject static_assert(false, ...), even inside an
54 // uninstantiated template.
55 static_assert(!IsOnceCallback<CallbackType>::value,
56 "OnceCallback::Run() may only be invoked on an rvalue, i.e. "
57 "std::move(callback).Run().");
tzik 2016/11/22 07:39:03 Hmm, OK, let's go this way. I prefer just deleting
58 }
59
39 R Run(Args... args) && { 60 R Run(Args... args) && {
40 // Move the callback instance into a local variable before the invocation, 61 // Move the callback instance into a local variable before the invocation,
41 // that ensures the internal state is cleared after the invocation. 62 // that ensures the internal state is cleared after the invocation.
42 // It's not safe to touch |this| after the invocation, since running the 63 // It's not safe to touch |this| after the invocation, since running the
43 // bound function may destroy |this|. 64 // bound function may destroy |this|.
44 CallbackType cb = static_cast<CallbackType&&>(*this); 65 CallbackType cb = static_cast<CallbackType&&>(*this);
45 PolymorphicInvoke f = 66 PolymorphicInvoke f =
46 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke()); 67 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
47 return f(cb.bind_state_.get(), std::forward<Args>(args)...); 68 return f(cb.bind_state_.get(), std::forward<Args>(args)...);
48 } 69 }
49 }; 70 };
50 71
51 // Specialization for RepeatingCallback. 72 // Specialization for RepeatingCallback.
52 template <typename R, typename... Args, CopyMode copy_mode> 73 template <typename R, typename... Args>
53 class RunMixin<Callback<R(Args...), copy_mode, RepeatMode::Repeating>> { 74 class RunMixin<RepeatingCallback<R(Args...)>> {
54 private: 75 private:
55 using CallbackType = Callback<R(Args...), copy_mode, RepeatMode::Repeating>; 76 using CallbackType = RepeatingCallback<R(Args...)>;
56 77
57 public: 78 public:
58 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...); 79 using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...);
59 80
60 R Run(Args... args) const { 81 R Run(Args... args) const {
61 const CallbackType& cb = static_cast<const CallbackType&>(*this); 82 const CallbackType& cb = static_cast<const CallbackType&>(*this);
62 PolymorphicInvoke f = 83 PolymorphicInvoke f =
63 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke()); 84 reinterpret_cast<PolymorphicInvoke>(cb.polymorphic_invoke());
64 return f(cb.bind_state_.get(), std::forward<Args>(args)...); 85 return f(cb.bind_state_.get(), std::forward<Args>(args)...);
65 } 86 }
66 }; 87 };
67 88
68 template <typename From, typename To> 89 template <typename From, typename To>
69 struct IsCallbackConvertible : std::false_type {}; 90 struct IsCallbackConvertible : std::false_type {};
70 91
71 template <typename Signature> 92 template <typename Signature>
72 struct IsCallbackConvertible< 93 struct IsCallbackConvertible<RepeatingCallback<Signature>,
73 Callback<Signature, CopyMode::Copyable, RepeatMode::Repeating>, 94 OnceCallback<Signature>> : std::true_type {};
74 Callback<Signature, CopyMode::MoveOnly, RepeatMode::Once>> : std::true_type {
75 };
76 95
77 } // namespace internal 96 } // namespace internal
78 97
79 template <typename R, 98 template <typename R,
80 typename... Args, 99 typename... Args,
81 internal::CopyMode copy_mode, 100 internal::CopyMode copy_mode,
82 internal::RepeatMode repeat_mode> 101 internal::RepeatMode repeat_mode>
83 class Callback<R(Args...), copy_mode, repeat_mode> 102 class Callback<R(Args...), copy_mode, repeat_mode>
84 : public internal::CallbackBase<copy_mode>, 103 : public internal::CallbackBase<copy_mode>,
85 public internal::RunMixin<Callback<R(Args...), copy_mode, repeat_mode>> { 104 public internal::RunMixin<Callback<R(Args...), copy_mode, repeat_mode>> {
(...skipping 29 matching lines...) Expand all
115 bool Equals(const Callback& other) const { 134 bool Equals(const Callback& other) const {
116 return this->EqualsInternal(other); 135 return this->EqualsInternal(other);
117 } 136 }
118 137
119 friend class internal::RunMixin<Callback>; 138 friend class internal::RunMixin<Callback>;
120 }; 139 };
121 140
122 } // namespace base 141 } // namespace base
123 142
124 #endif // BASE_CALLBACK_H_ 143 #endif // BASE_CALLBACK_H_
OLDNEW
« no previous file with comments | « base/bind_unittest.nc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698