1 /* 2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 // To generate bind.h from bind.h.pump, execute: 12 // /home/build/google3/third_party/gtest/scripts/pump.py bind.h.pump 13 14 // Bind() is an overloaded function that converts method calls into function 15 // objects (aka functors). It captures any arguments to the method by value 16 // when Bind is called, producing a stateful, nullary function object. Care 17 // should be taken about the lifetime of objects captured by Bind(); the 18 // returned functor knows nothing about the lifetime of the method's object or 19 // any arguments passed by pointer, and calling the functor with a destroyed 20 // object will surely do bad things. 21 // 22 // Example usage: 23 // struct Foo { 24 // int Test1() { return 42; } 25 // int Test2() const { return 52; } 26 // int Test3(int x) { return x*x; } 27 // float Test4(int x, float y) { return x + y; } 28 // }; 29 // 30 // int main() { 31 // Foo foo; 32 // cout << rtc::Bind(&Foo::Test1, &foo)() << endl; 33 // cout << rtc::Bind(&Foo::Test2, &foo)() << endl; 34 // cout << rtc::Bind(&Foo::Test3, &foo, 3)() << endl; 35 // cout << rtc::Bind(&Foo::Test4, &foo, 7, 8.5f)() << endl; 36 // } 37 38 #ifndef WEBRTC_BASE_BIND_H_ 39 #define WEBRTC_BASE_BIND_H_ 40 41 #define NONAME 42 43 namespace rtc { 44 namespace detail { 45 // This is needed because the template parameters in Bind can't be resolved 46 // if they're used both as parameters of the function pointer type and as 47 // parameters to Bind itself: the function pointer parameters are exact 48 // matches to the function prototype, but the parameters to bind have 49 // references stripped. This trick allows the compiler to dictate the Bind 50 // parameter types rather than deduce them. 51 template <class T> struct identity { typedef T type; }; 52 } // namespace detail 53 54 $var n = 5 55 $range i 0..n 56 $for i [[ 57 $range j 1..i 58 59 template <class ObjectT, class MethodT, class R$for j [[, 60 class P$j]]> 61 class MethodFunctor$i { 62 public: 63 MethodFunctor$i(MethodT method, ObjectT* object$for j [[, 64 P$j p$j]]) 65 : method_(method), object_(object)$for j [[, 66 p$(j)_(p$j)]] {} 67 R operator()() const { 68 return (object_->*method_)($for j , [[p$(j)_]]); } 69 private: 70 MethodT method_; 71 ObjectT* object_;$for j [[ 72 73 P$j p$(j)_;]] 74 75 }; 76 77 template <class FunctorT, class R$for j [[, 78 class P$j]]> 79 class Functor$i { 80 public: 81 $if i == 0 [[explicit ]] 82 Functor$i(const FunctorT& functor$for j [[, P$j p$j]]) 83 : functor_(functor)$for j [[, 84 p$(j)_(p$j)]] {} 85 R operator()() const { 86 return functor_($for j , [[p$(j)_]]); } 87 private: 88 FunctorT functor_;$for j [[ 89 90 P$j p$(j)_;]] 91 92 }; 93 94 95 #define FP_T(x) R (ObjectT::*x)($for j , [[P$j]]) 96 97 template <class ObjectT, class R$for j [[, 98 class P$j]]> 99 MethodFunctor$i<ObjectT, FP_T(NONAME), R$for j [[, P$j]]> 100 Bind(FP_T(method), ObjectT* object$for j [[, 101 typename detail::identity<P$j>::type p$j]]) { 102 return MethodFunctor$i<ObjectT, FP_T(NONAME), R$for j [[, P$j]]>( 103 method, object$for j [[, p$j]]); 104 } 105 106 #undef FP_T 107 #define FP_T(x) R (ObjectT::*x)($for j , [[P$j]]) const 108 109 template <class ObjectT, class R$for j [[, 110 class P$j]]> 111 MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]> 112 Bind(FP_T(method), const ObjectT* object$for j [[, 113 typename detail::identity<P$j>::type p$j]]) { 114 return MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]>( 115 method, object$for j [[, p$j]]); 116 } 117 118 #undef FP_T 119 #define FP_T(x) R (*x)($for j , [[P$j]]) 120 121 template <class R$for j [[, 122 class P$j]]> 123 Functor$i<FP_T(NONAME), R$for j [[, P$j]]> 124 Bind(FP_T(function)$for j [[, 125 typename detail::identity<P$j>::type p$j]]) { 126 return Functor$i<FP_T(NONAME), R$for j [[, P$j]]>( 127 function$for j [[, p$j]]); 128 } 129 130 #undef FP_T 131 132 ]] 133 134 } // namespace rtc 135 136 #undef NONAME 137 138 #endif // WEBRTC_BASE_BIND_H_ 139