[email protected] | b38d357 | 2011-02-15 01:27:38 | [diff] [blame] | 1 | // Copyright (c) 2011 The Chromium 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 BASE_BIND_H_ |
| 6 | #define BASE_BIND_H_ |
[email protected] | b38d357 | 2011-02-15 01:27:38 | [diff] [blame] | 7 | |
| 8 | #include "base/bind_internal.h" |
[email protected] | 59eff91 | 2011-02-18 23:29:31 | [diff] [blame] | 9 | #include "base/callback_internal.h" |
[email protected] | b38d357 | 2011-02-15 01:27:38 | [diff] [blame] | 10 | |
[email protected] | 2429264 | 2012-07-12 20:06:40 | [diff] [blame] | 11 | // ----------------------------------------------------------------------------- |
| 12 | // Usage documentation |
| 13 | // ----------------------------------------------------------------------------- |
[email protected] | b38d357 | 2011-02-15 01:27:38 | [diff] [blame] | 14 | // |
[email protected] | 2429264 | 2012-07-12 20:06:40 | [diff] [blame] | 15 | // See base/callback.h for documentation. |
| 16 | // |
| 17 | // |
| 18 | // ----------------------------------------------------------------------------- |
| 19 | // Implementation notes |
| 20 | // ----------------------------------------------------------------------------- |
| 21 | // |
| 22 | // If you're reading the implementation, before proceeding further, you should |
| 23 | // read the top comment of base/bind_internal.h for a definition of common |
| 24 | // terms and concepts. |
| 25 | // |
| 26 | // RETURN TYPES |
| 27 | // |
[email protected] | b38d357 | 2011-02-15 01:27:38 | [diff] [blame] | 28 | // Though Bind()'s result is meant to be stored in a Callback<> type, it |
| 29 | // cannot actually return the exact type without requiring a large amount |
| 30 | // of extra template specializations. The problem is that in order to |
| 31 | // discern the correct specialization of Callback<>, Bind would need to |
| 32 | // unwrap the function signature to determine the signature's arity, and |
| 33 | // whether or not it is a method. |
| 34 | // |
| 35 | // Each unique combination of (arity, function_type, num_prebound) where |
| 36 | // function_type is one of {function, method, const_method} would require |
| 37 | // one specialization. We eventually have to do a similar number of |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 38 | // specializations anyways in the implementation (see the Invoker<>, |
[email protected] | b38d357 | 2011-02-15 01:27:38 | [diff] [blame] | 39 | // classes). However, it is avoidable in Bind if we return the result |
| 40 | // via an indirection like we do below. |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 41 | // |
| 42 | // TODO(ajwong): We might be able to avoid this now, but need to test. |
| 43 | // |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 44 | // It is possible to move most of the static_assert into BindState<>, but it |
| 45 | // feels a little nicer to have the asserts here so people do not need to crack |
| 46 | // open bind_internal.h. On the other hand, it makes Bind() harder to read. |
[email protected] | b38d357 | 2011-02-15 01:27:38 | [diff] [blame] | 47 | |
| 48 | namespace base { |
| 49 | |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 50 | template <typename Functor, typename... Args> |
[email protected] | e24f876 | 2011-12-20 00:10:04 | [diff] [blame] | 51 | base::Callback< |
| 52 | typename internal::BindState< |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 53 | typename internal::FunctorTraits<Functor>::RunnableType, |
| 54 | typename internal::FunctorTraits<Functor>::RunType, |
tzik | ce3ecf8 | 2015-12-15 06:41:49 | [diff] [blame] | 55 | typename internal::CallbackParamTraits<Args>::StorageType...> |
[email protected] | e24f876 | 2011-12-20 00:10:04 | [diff] [blame] | 56 | ::UnboundRunType> |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 57 | Bind(Functor functor, const Args&... args) { |
tzik | 3bc7779b | 2015-12-19 09:18:46 | [diff] [blame] | 58 | // Type aliases for how to store and run the functor. |
| 59 | using RunnableType = typename internal::FunctorTraits<Functor>::RunnableType; |
| 60 | using RunType = typename internal::FunctorTraits<Functor>::RunType; |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 61 | |
| 62 | // Use RunnableType::RunType instead of RunType above because our |
tzik | 3bc7779b | 2015-12-19 09:18:46 | [diff] [blame] | 63 | // checks below for bound references need to know what the actual |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 64 | // functor is going to interpret the argument as. |
tzik | 3bc7779b | 2015-12-19 09:18:46 | [diff] [blame] | 65 | using BoundRunType = typename RunnableType::RunType; |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 66 | |
tzik | 7fe3a68 | 2015-12-18 02:23:26 | [diff] [blame] | 67 | using BoundArgs = |
| 68 | internal::TakeTypeListItem<sizeof...(Args), |
| 69 | internal::ExtractArgs<BoundRunType>>; |
| 70 | |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 71 | // Do not allow binding a non-const reference parameter. Non-const reference |
| 72 | // parameters are disallowed by the Google style guide. Also, binding a |
| 73 | // non-const reference parameter can make for subtle bugs because the |
| 74 | // invoked function will receive a reference to the stored copy of the |
| 75 | // argument and not the original. |
tzik | 7fe3a68 | 2015-12-18 02:23:26 | [diff] [blame] | 76 | static_assert(!internal::HasNonConstReferenceItem<BoundArgs>::value, |
avi | 4ec0dff | 2015-11-24 14:26:24 | [diff] [blame] | 77 | "do not bind functions with nonconst ref"); |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 78 | |
| 79 | const bool is_method = internal::HasIsMethodTag<RunnableType>::value; |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 80 | |
| 81 | // For methods, we need to be careful for parameter 1. We do not require |
| 82 | // a scoped_refptr because BindState<> itself takes care of AddRef() for |
| 83 | // methods. We also disallow binding of an array as the method's target |
| 84 | // object. |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 85 | static_assert(!internal::BindsArrayToFirstArg<is_method, Args...>::value, |
avi | 4ec0dff | 2015-11-24 14:26:24 | [diff] [blame] | 86 | "first bound argument to method cannot be array"); |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 87 | static_assert( |
| 88 | !internal::HasRefCountedParamAsRawPtr<is_method, Args...>::value, |
avi | 4ec0dff | 2015-11-24 14:26:24 | [diff] [blame] | 89 | "a parameter is a refcounted type and needs scoped_refptr"); |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 90 | |
tzik | 3bc7779b | 2015-12-19 09:18:46 | [diff] [blame] | 91 | using BindState = internal::BindState< |
tzik | 8ce6570 | 2015-02-05 19:11:26 | [diff] [blame] | 92 | RunnableType, RunType, |
tzik | 3bc7779b | 2015-12-19 09:18:46 | [diff] [blame] | 93 | typename internal::CallbackParamTraits<Args>::StorageType...>; |
[email protected] | e24f876 | 2011-12-20 00:10:04 | [diff] [blame] | 94 | |
| 95 | return Callback<typename BindState::UnboundRunType>( |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 96 | new BindState(internal::MakeRunnable(functor), args...)); |
[email protected] | fccef155 | 2011-11-28 22:13:54 | [diff] [blame] | 97 | } |
| 98 | |
[email protected] | b38d357 | 2011-02-15 01:27:38 | [diff] [blame] | 99 | } // namespace base |
| 100 | |
| 101 | #endif // BASE_BIND_H_ |