Chromium Code Reviews| Index: base/callback.h |
| diff --git a/base/callback.h b/base/callback.h |
| index c6b8ca3c448a92fbcf0be7d083f63e3aa852aec5..344acfe65cbb230abcfb74ba46c2d4bd7c8bd6f2 100644 |
| --- a/base/callback.h |
| +++ b/base/callback.h |
| @@ -21,6 +21,12 @@ namespace base { |
| namespace internal { |
| +template <typename CallbackType> |
| +struct IsOnceCallback : std::false_type {}; |
| + |
| +template <typename Signature> |
| +struct IsOnceCallback<OnceCallback<Signature>> : std::true_type {}; |
| + |
| // RunMixin provides different variants of `Run()` function to `Callback<>` |
| // based on the type of callback. |
| template <typename CallbackType> |
| @@ -28,14 +34,29 @@ class RunMixin; |
| // Specialization for OnceCallback. |
| template <typename R, typename... Args> |
| -class RunMixin<Callback<R(Args...), CopyMode::MoveOnly, RepeatMode::Once>> { |
| +class RunMixin<OnceCallback<R(Args...)>> { |
| private: |
| - using CallbackType = |
| - Callback<R(Args...), CopyMode::MoveOnly, RepeatMode::Once>; |
| + using CallbackType = OnceCallback<R(Args...)>; |
| public: |
| using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...); |
| + R Run(Args... args) & { |
| + // Note: even though this static_assert will trivially always fail, it |
| + // cannot be simply replaced with static_assert(false, ...) because: |
| + // - Per [dcl.dcl]/p4, a program is ill-formed if the constant-expression |
| + // argument does not evaluate to true. |
| + // - Per [temp.res]/p8, if no valid specialization can be generated for a |
| + // template definition, and that template is not instantiated, the |
| + // template definition is ill-formed, no diagnostic required. |
| + // These two clauses, taken together, would allow a conforming C++ compiler |
| + // to immediately reject static_assert(false, ...), even inside an |
| + // uninstantiated template. |
| + static_assert(!IsOnceCallback<CallbackType>::value, |
| + "OnceCallback::Run() may only be invoked on an rvalue, i.e. " |
| + "std::move(callback).Run()."); |
|
tzik
2016/11/22 07:39:03
Hmm, OK, let's go this way.
I prefer just deleting
|
| + } |
| + |
| R Run(Args... args) && { |
| // Move the callback instance into a local variable before the invocation, |
| // that ensures the internal state is cleared after the invocation. |
| @@ -49,10 +70,10 @@ class RunMixin<Callback<R(Args...), CopyMode::MoveOnly, RepeatMode::Once>> { |
| }; |
| // Specialization for RepeatingCallback. |
| -template <typename R, typename... Args, CopyMode copy_mode> |
| -class RunMixin<Callback<R(Args...), copy_mode, RepeatMode::Repeating>> { |
| +template <typename R, typename... Args> |
| +class RunMixin<RepeatingCallback<R(Args...)>> { |
| private: |
| - using CallbackType = Callback<R(Args...), copy_mode, RepeatMode::Repeating>; |
| + using CallbackType = RepeatingCallback<R(Args...)>; |
| public: |
| using PolymorphicInvoke = R(*)(internal::BindStateBase*, Args&&...); |
| @@ -69,10 +90,8 @@ template <typename From, typename To> |
| struct IsCallbackConvertible : std::false_type {}; |
| template <typename Signature> |
| -struct IsCallbackConvertible< |
| - Callback<Signature, CopyMode::Copyable, RepeatMode::Repeating>, |
| - Callback<Signature, CopyMode::MoveOnly, RepeatMode::Once>> : std::true_type { |
| -}; |
| +struct IsCallbackConvertible<RepeatingCallback<Signature>, |
| + OnceCallback<Signature>> : std::true_type {}; |
| } // namespace internal |