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.
8 #include "base/bind_internal.h"
9 #include "base/callback_internal.h"
11 // -----------------------------------------------------------------------------
12 // Usage documentation
13 // -----------------------------------------------------------------------------
15 // See base/callback.h for documentation.
18 // -----------------------------------------------------------------------------
19 // Implementation notes
20 // -----------------------------------------------------------------------------
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.
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.
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
38 // specializations anyways in the implementation (see the Invoker<>,
39 // classes). However, it is avoidable in Bind if we return the result
40 // via an indirection like we do below.
42 // TODO(ajwong): We might be able to avoid this now, but need to test.
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.
50 template <typename Functor
>
52 typename
internal::BindState
<
53 typename
internal::FunctorTraits
<Functor
>::RunnableType
,
54 typename
internal::FunctorTraits
<Functor
>::RunType
,
55 internal::TypeList
<>>::UnboundRunType
>
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
;
61 typedef internal::BindState
<RunnableType
, RunType
,
62 internal::TypeList
<>> BindState
;
64 return Callback
<typename
BindState::UnboundRunType
>(
65 new BindState(internal::MakeRunnable(functor
)));
68 template <typename Functor
, typename
... Args
>
70 typename
internal::BindState
<
71 typename
internal::FunctorTraits
<Functor
>::RunnableType
,
72 typename
internal::FunctorTraits
<Functor
>::RunType
,
74 typename
internal::CallbackParamTraits
<Args
>::StorageType
...>>
76 Bind(Functor functor
, const Args
&... args
) {
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
;
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.
84 typedef typename
RunnableType::RunType BoundRunType
;
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.
91 static_assert(!internal::HasNonConstReferenceParam
<BoundRunType
>::value
,
92 "do_not_bind_functions_with_nonconst_ref");
94 const bool is_method
= internal::HasIsMethodTag
<RunnableType
>::value
;
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
100 static_assert(!internal::BindsArrayToFirstArg
<is_method
, Args
...>::value
,
101 "first_bound_argument_to_method_cannot_be_array");
103 !internal::HasRefCountedParamAsRawPtr
<is_method
, Args
...>::value
,
104 "a_parameter_is_refcounted_type_and_needs_scoped_refptr");
106 typedef internal::BindState
<
107 RunnableType
, RunType
,
109 typename
internal::CallbackParamTraits
<Args
>::StorageType
...>>
112 return Callback
<typename
BindState::UnboundRunType
>(
113 new BindState(internal::MakeRunnable(functor
), args
...));
118 #endif // BASE_BIND_H_