[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 | |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 50 | template <typename Functor> |
[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 | 8ce6570 | 2015-02-05 19:11:26 | [diff] [blame^] | 55 | internal::TypeList<>>::UnboundRunType> |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 56 | Bind(Functor functor) { |
| 57 | // Typedefs for how to store and run the functor. |
| 58 | typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType; |
| 59 | typedef typename internal::FunctorTraits<Functor>::RunType RunType; |
| 60 | |
tzik | 8ce6570 | 2015-02-05 19:11:26 | [diff] [blame^] | 61 | typedef internal::BindState<RunnableType, RunType, |
| 62 | internal::TypeList<>> BindState; |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 63 | |
[email protected] | e24f876 | 2011-12-20 00:10:04 | [diff] [blame] | 64 | return Callback<typename BindState::UnboundRunType>( |
| 65 | new BindState(internal::MakeRunnable(functor))); |
[email protected] | b38d357 | 2011-02-15 01:27:38 | [diff] [blame] | 66 | } |
| 67 | |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 68 | template <typename Functor, typename... Args> |
[email protected] | e24f876 | 2011-12-20 00:10:04 | [diff] [blame] | 69 | base::Callback< |
| 70 | typename internal::BindState< |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 71 | typename internal::FunctorTraits<Functor>::RunnableType, |
| 72 | typename internal::FunctorTraits<Functor>::RunType, |
tzik | 8ce6570 | 2015-02-05 19:11:26 | [diff] [blame^] | 73 | internal::TypeList< |
| 74 | typename internal::CallbackParamTraits<Args>::StorageType...>> |
[email protected] | e24f876 | 2011-12-20 00:10:04 | [diff] [blame] | 75 | ::UnboundRunType> |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 76 | Bind(Functor functor, const Args&... args) { |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 77 | // Typedefs for how to store and run the functor. |
| 78 | typedef typename internal::FunctorTraits<Functor>::RunnableType RunnableType; |
| 79 | typedef typename internal::FunctorTraits<Functor>::RunType RunType; |
| 80 | |
| 81 | // Use RunnableType::RunType instead of RunType above because our |
| 82 | // checks should below for bound references need to know what the actual |
| 83 | // functor is going to interpret the argument as. |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 84 | typedef typename RunnableType::RunType BoundRunType; |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 85 | |
| 86 | // Do not allow binding a non-const reference parameter. Non-const reference |
| 87 | // parameters are disallowed by the Google style guide. Also, binding a |
| 88 | // non-const reference parameter can make for subtle bugs because the |
| 89 | // invoked function will receive a reference to the stored copy of the |
| 90 | // argument and not the original. |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 91 | static_assert(!internal::HasNonConstReferenceParam<BoundRunType>::value, |
| 92 | "do_not_bind_functions_with_nonconst_ref"); |
| 93 | |
| 94 | const bool is_method = internal::HasIsMethodTag<RunnableType>::value; |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 95 | |
| 96 | // For methods, we need to be careful for parameter 1. We do not require |
| 97 | // a scoped_refptr because BindState<> itself takes care of AddRef() for |
| 98 | // methods. We also disallow binding of an array as the method's target |
| 99 | // object. |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 100 | static_assert(!internal::BindsArrayToFirstArg<is_method, Args...>::value, |
| 101 | "first_bound_argument_to_method_cannot_be_array"); |
| 102 | static_assert( |
| 103 | !internal::HasRefCountedParamAsRawPtr<is_method, Args...>::value, |
| 104 | "a_parameter_is_refcounted_type_and_needs_scoped_refptr"); |
[email protected] | 7296f276 | 2011-11-21 19:23:44 | [diff] [blame] | 105 | |
tzik | 8ce6570 | 2015-02-05 19:11:26 | [diff] [blame^] | 106 | typedef internal::BindState< |
| 107 | RunnableType, RunType, |
| 108 | internal::TypeList< |
| 109 | typename internal::CallbackParamTraits<Args>::StorageType...>> |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 110 | BindState; |
[email protected] | e24f876 | 2011-12-20 00:10:04 | [diff] [blame] | 111 | |
| 112 | return Callback<typename BindState::UnboundRunType>( |
tzik | 401dd367 | 2014-11-26 07:54:58 | [diff] [blame] | 113 | new BindState(internal::MakeRunnable(functor), args...)); |
[email protected] | fccef155 | 2011-11-28 22:13:54 | [diff] [blame] | 114 | } |
| 115 | |
[email protected] | b38d357 | 2011-02-15 01:27:38 | [diff] [blame] | 116 | } // namespace base |
| 117 | |
| 118 | #endif // BASE_BIND_H_ |