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 43namespace rtc { 44namespace 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. 51template <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 59template <class ObjectT, class MethodT, class R$for j [[, 60 class P$j]]> 61class 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 77template <class FunctorT, class R$for j [[, 78 class P$j]]> 79class Functor$i { 80 public: 81 $if i == 0 [[explicit ]] 82Functor$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 97template <class ObjectT, class R$for j [[, 98 class P$j]]> 99MethodFunctor$i<ObjectT, FP_T(NONAME), R$for j [[, P$j]]> 100Bind(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 109template <class ObjectT, class R$for j [[, 110 class P$j]]> 111MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]> 112Bind(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 121template <class R$for j [[, 122 class P$j]]> 123Functor$i<FP_T(NONAME), R$for j [[, P$j]]> 124Bind(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