blob: 51be10dd7e65c0d4226ab4542cc346578cee8a0b [file] [log] [blame]
[email protected]b38d3572011-02-15 01:27:381// 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]b38d3572011-02-15 01:27:387
8#include "base/bind_internal.h"
[email protected]59eff912011-02-18 23:29:319#include "base/callback_internal.h"
[email protected]b38d3572011-02-15 01:27:3810
[email protected]24292642012-07-12 20:06:4011// -----------------------------------------------------------------------------
12// Usage documentation
13// -----------------------------------------------------------------------------
[email protected]b38d3572011-02-15 01:27:3814//
[email protected]24292642012-07-12 20:06:4015// 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]b38d3572011-02-15 01:27:3828// 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]7296f2762011-11-21 19:23:4438// specializations anyways in the implementation (see the Invoker<>,
[email protected]b38d3572011-02-15 01:27:3839// classes). However, it is avoidable in Bind if we return the result
40// via an indirection like we do below.
[email protected]7296f2762011-11-21 19:23:4441//
42// TODO(ajwong): We might be able to avoid this now, but need to test.
43//
tzik401dd3672014-11-26 07:54:5844// 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]b38d3572011-02-15 01:27:3847
48namespace base {
49
[email protected]7296f2762011-11-21 19:23:4450template <typename Functor>
[email protected]e24f8762011-12-20 00:10:0451base::Callback<
52 typename internal::BindState<
[email protected]7296f2762011-11-21 19:23:4453 typename internal::FunctorTraits<Functor>::RunnableType,
54 typename internal::FunctorTraits<Functor>::RunType,
tzik8ce65702015-02-05 19:11:2655 internal::TypeList<>>::UnboundRunType>
[email protected]7296f2762011-11-21 19:23:4456Bind(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
tzik8ce65702015-02-05 19:11:2661 typedef internal::BindState<RunnableType, RunType,
62 internal::TypeList<>> BindState;
[email protected]7296f2762011-11-21 19:23:4463
[email protected]e24f8762011-12-20 00:10:0464 return Callback<typename BindState::UnboundRunType>(
65 new BindState(internal::MakeRunnable(functor)));
[email protected]b38d3572011-02-15 01:27:3866}
67
tzik401dd3672014-11-26 07:54:5868template <typename Functor, typename... Args>
[email protected]e24f8762011-12-20 00:10:0469base::Callback<
70 typename internal::BindState<
[email protected]7296f2762011-11-21 19:23:4471 typename internal::FunctorTraits<Functor>::RunnableType,
72 typename internal::FunctorTraits<Functor>::RunType,
tzik8ce65702015-02-05 19:11:2673 internal::TypeList<
74 typename internal::CallbackParamTraits<Args>::StorageType...>>
[email protected]e24f8762011-12-20 00:10:0475 ::UnboundRunType>
tzik401dd3672014-11-26 07:54:5876Bind(Functor functor, const Args&... args) {
[email protected]7296f2762011-11-21 19:23:4477 // 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.
tzik401dd3672014-11-26 07:54:5884 typedef typename RunnableType::RunType BoundRunType;
[email protected]7296f2762011-11-21 19:23:4485
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.
tzik401dd3672014-11-26 07:54:5891 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]7296f2762011-11-21 19:23:4495
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.
tzik401dd3672014-11-26 07:54:58100 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]7296f2762011-11-21 19:23:44105
tzik8ce65702015-02-05 19:11:26106 typedef internal::BindState<
107 RunnableType, RunType,
108 internal::TypeList<
109 typename internal::CallbackParamTraits<Args>::StorageType...>>
tzik401dd3672014-11-26 07:54:58110 BindState;
[email protected]e24f8762011-12-20 00:10:04111
112 return Callback<typename BindState::UnboundRunType>(
tzik401dd3672014-11-26 07:54:58113 new BindState(internal::MakeRunnable(functor), args...));
[email protected]fccef1552011-11-28 22:13:54114}
115
[email protected]b38d3572011-02-15 01:27:38116} // namespace base
117
118#endif // BASE_BIND_H_