AFL Code/libFuzzer Code quick copy
int main(int argc, char** argv) { if(argc>1){ FILE *f = fopen(argv[1], "rb"); fseek(f, 0, SEEK_END); size_t fsize = ftell(f); rewind(f); uint8_t* str = (uint8_t *)malloc(fsize + 1); memset(str, 0, fsize + 1); fread((void*)str, fsize, 1, f); fclose(f); LLVMFuzzerTestOneInput(str, fsize + 1); free(str); str = (uint8_t*)0; } else { uint8_t* str = (uint8_t *)malloc(4096); memset(str, 0, 4096); fgets((char*)str, 4095, stdin); LLVMFuzzerTestOneInput(str, 4096); free(str); str = (uint8_t*)0; } return 0; } =========== clang++ -g -fsanitize=fuzzer,address,undefined -fsanitize-coverage=trace-pc-guard FTS/tutorial/fuzz_me.cc libFuzzer.a extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { DoSomethingWithData(data, size); return 0; }
Document of bind_internal.h in mojo
有关用户文档,请参见base/callback.h。
概念:
————————–
O Runnable — 这个类型(实际上是类型类, type class)具有单个Run()方法,以及对应于Run()的类型的RunType typedef。
Runnable可以通过包含名为IsMethod的typedef来声明它应该被视为方法调用。
该类型函数的值不会被检查,只检查存在的值。
当Runnable声明自己是一个方法时,Bind()将对预期是对象类型的第一个参数强制执行特殊的refcount+WeakPtr处理语义。
O Functor — 一个可复制的类型,表示某个应该被调用的东西。
即使调用语法不同,所有函数指针、Callback<>和Runnables都是仿函数(functor)。
O RunType — Run()函数的函数类型(与函数*指针*类型相反)。
通常只是一种方便的typedef。
O (Bound)ArgsType — 用于存储一组参数的类型的函数类型。
“return”类型在此处始终为void。
使用这种方法,这样我们就不需要为每个类型指定一个新的类型名称。(例如,BindState1、BindState2)。这使得向前声明和友元(Friending)变得容易得多。
类型:
————————–
O RunnableAdapter<> — 将各种“函数”指针类型封装到一个依附于Runnable接口的对象中。
O ForceVoidReturn<> — Helper类,用于将函数特征转换为具有“void”返回类型的等效形式。
O FunctorTraits<> — 使用的类型特征确定仿函数的正确RunType和RunnableType。这是应用函数特征适配器的地方。
O MakeRunnable<> — 接受一个仿函数,并在Runnable类型类中返回一个表示底层仿函数的对象。有|O(1)|的MakeRunnable类型。
O invokeHelper<> — 采用runnable+参数并实际调用它。
处理WeakPtr<>支持和忽略返回值所需的不同语法。这与调用程序是分开的,以避免创建多个版本的Callback<>。
O Invoker<> — 解包curried参数并执行Runnable。
O BindState<> — 存储已绑定的参数,并作为Bind()系统的主要入口点,执行大部分类型解析。存在多个BindState类型。
当|Sig|中的任何参数为非常量引用时,HasNonConstReferenceParam选择true_type。
实例时请注意:此非特化情况仅能处理zero-arity案例。
非zero-arity情况应由以下特化处理。
—————————
实际代码
template <typename Sig> struct HasNonConstReferenceParam : false_type {};
实现注意:如果第一个参数是非const引用,则选择true_type。否则,跳过第一个参数并递归地检查其余的参数。
template <typename R, typename T, typename... Args> struct HasNonConstReferenceParam<R(T, Args...)> : SelectType<is_non_const_reference<T>::value, true_type, HasNonConstReferenceParam<R(Args...)>>::Type {};
当|ARGS|中的任何一个是指向RefCounted类型的原始指针时,HasRefCountedTypeAsRawPtr选择true_type。
实施注意:此非特化案例仅处理zero-arity的情况。
非zero-arity的情况应由以下特化处理。
template <typename... Args> struct HasRefCountedTypeAsRawPtr : false_type {};
实施注意事项:如果第一个参数是指向RefCounted类型的原始指针,请选择true_type。否则,跳过第一个参数并递归地检查其余的参数。
template <typename T, typename... Args> struct HasRefCountedTypeAsRawPtr<T, Args...> : SelectType<NeedsScopedRefptrButGetsRawPtr<T>::value, true_type, HasRefCountedTypeAsRawPtr<Args...>>::Type {};
当|is_method|为true且|Args|的第一项为数组类型时,BindsArrayToFirstArg选择true_type。
实现注意:此非特化案例仅处理!is_method的情况和zero-arity的情况。
其他情况应由以下特化代码处理。
template <bool is_method, typename... Args> struct BindsArrayToFirstArg : false_type {}; template <typename T, typename... Args> struct BindsArrayToFirstArg<true, T, Args...> : is_array<T> {};
HasRefCountedParamAsRawPtr与HasRefCountedTypeAsRawPtr相同,除非|is_method|为true,HasRefCountedParamAsRawPtr跳过第一个参数。
实现注意:此非特化案例仅处理!is_method的情况和zero-arity的情况。
其他情况应由以下特化代码处理。
template <bool is_method, typename... Args> struct HasRefCountedParamAsRawPtr : HasRefCountedTypeAsRawPtr<Args...> {}; template <typename T, typename... Args> struct HasRefCountedParamAsRawPtr<true, T, Args...> : HasRefCountedTypeAsRawPtr<Args...> {};
RunnableAdapter<>
RunnableAdapter<>模板为调用函数指针、方法指针或const方法指针提供了统一的接口。适配器公开具有适当签名的Run()方法。
使用这个包装器可以编写支持所有三种指针类型的代码,而不会有不必要的重复。
没有它,许多代码将需要重复3次。
对于方法的指针和const方法的指针,第一个要Run()的参数被认为是被接收到的方法。这类似于STL的mem_fun()。
此类还公开了 RunType typedef ,它是Run()函数的函数类型。
当且仅当包装器包含方法或const方法指针时,将暴露IsMethod typedef。
该类型函数(而不是值)的存在表明wrapper应该被视为method wrapper。
template <typename Functor> class RunnableAdapter; // Function. template <typename R, typename... Args> class RunnableAdapter<R(*)(Args...)> { public: typedef R (RunType)(Args...); explicit RunnableAdapter(R(*function)(Args...)) : function_(function) { } R Run(typename CallbackParamTraits<Args>::ForwardType... args) { return function_(CallbackForward(args)...); } private: R (*function_)(Args...); }; // Method. template <typename R, typename T, typename... Args> class RunnableAdapter<R(T::*)(Args...)> { public: typedef R (RunType)(T*, Args...); typedef true_type IsMethod; explicit RunnableAdapter(R(T::*method)(Args...)) : method_(method) { } R Run(T* object, typename CallbackParamTraits<Args>::ForwardType... args) { return (object->*method_)(CallbackForward(args)...); } private: R (T::*method_)(Args...); }; // Const Method. template <typename R, typename T, typename... Args> class RunnableAdapter<R(T::*)(Args...) const> { public: typedef R (RunType)(const T*, Args...); typedef true_type IsMethod; explicit RunnableAdapter(R(T::*method)(Args...) const) : method_(method) { } R Run(const T* object, typename CallbackParamTraits<Args>::ForwardType... args) { return (object->*method_)(CallbackForward(args)...); } private: R (T::*method_)(Args...) const; };
ForceVoidReturn<>
支持强制函数返回类型为空的一组模板。
template <typename Sig> struct ForceVoidReturn; template <typename R, typename... Args> struct ForceVoidReturn<R(Args...)> { typedef void(RunType)(Args...); }; // FunctorTraits<> // // See description at top of file. template <typename T> struct FunctorTraits { typedef RunnableAdapter<T> RunnableType; typedef typename RunnableType::RunType RunType; }; template <typename T> struct FunctorTraits<IgnoreResultHelper<T>> { typedef typename FunctorTraits<T>::RunnableType RunnableType; typedef typename ForceVoidReturn< typename RunnableType::RunType>::RunType RunType; }; template <typename T> struct FunctorTraits<Callback<T>> { typedef Callback<T> RunnableType; typedef typename Callback<T>::RunType RunType; };
MakeRunnable<>
使用类型推断将传入的仿函数转换为RunnableType。
template <typename T> typename FunctorTraits<T>::RunnableType MakeRunnable(const T& t) { return RunnableAdapter<T>(t); } template <typename T> typename FunctorTraits<T>::RunnableType MakeRunnable(const IgnoreResultHelper<T>& t) { return MakeRunnable(t.functor_); } template <typename T> const typename FunctorTraits<Callback<T>>::RunnableType& MakeRunnable(const Callback<T>& t) { DCHECK(!t.is_null()); return t; }
InvokeHelper<>
有3个逻辑InvokeHelper<>特化:normal、void-return、WeakCalls。
普通类型只调用基础Runnable。
为了支持IgnoreResult(),我们需要一个InvokeHelper来处理void返回类型。
通常,如果Runnable的RunType返回为空,则模板系统将只接“return functor.Run()”,而忽略了将void函数与Return一起使用这一事实。
当Runnable的RunType不是空的时,这个猜想就会被打破。
因此,我们需要部分特化来更改语法,从调用中删除“return”。
WeakCalls同样需要应用于第一个参数的特殊语法,以检查它们是否应该自己执行no-op。
template <bool IsWeakCall, typename ReturnType, typename Runnable, typename ArgsType> struct InvokeHelper; template <typename ReturnType, typename Runnable, typename... Args> struct InvokeHelper<false, ReturnType, Runnable, TypeList<Args...>> { static ReturnType MakeItSo(Runnable runnable, Args... args) { return runnable.Run(CallbackForward(args)...); } }; template <typename Runnable, typename... Args> struct InvokeHelper<false, void, Runnable, TypeList<Args...>> { static void MakeItSo(Runnable runnable, Args... args) { runnable.Run(CallbackForward(args)...); } }; template <typename Runnable, typename BoundWeakPtr, typename... Args> struct InvokeHelper<true, void, Runnable, TypeList<BoundWeakPtr, Args...>> { static void MakeItSo(Runnable runnable, BoundWeakPtr weak_ptr, Args... args) { if (!weak_ptr.get()) { return; } runnable.Run(weak_ptr.get(), CallbackForward(args)...); } }; #if !defined(_MSC_VER) template <typename ReturnType, typename Runnable, typename ArgsType> struct InvokeHelper<true, ReturnType, Runnable, ArgsType> {
WeakCall仅支持具有空返回类型的函数。
否则,如果WeakPtr<>无效,则不会定义函数结果。
COMPILE_ASSERT(is_void<ReturnType>::value, weak_ptrs_can_only_bind_to_methods_without_return_values); }; #endif // Invoker<> // // See description at the top of the file. template <typename BoundIndices, typename StorageType, typename Unwrappers, typename InvokeHelperType, typename UnboundForwardRunType> struct Invoker; template <size_t... bound_indices, typename StorageType, typename... Unwrappers, typename InvokeHelperType, typename R, typename... UnboundForwardArgs> struct Invoker<IndexSequence<bound_indices...>, StorageType, TypeList<Unwrappers...>, InvokeHelperType, R(UnboundForwardArgs...)> { static R Run(BindStateBase* base, UnboundForwardArgs... unbound_args) { StorageType* storage = static_cast<StorageType*>(base);
本地引用,使调试器调试更容易。
如果在调试器中,你肯定想要提前完成下面的InvokeHelper<>::MakeItSo()调用。
return InvokeHelperType::MakeItSo( storage->runnable_, Unwrappers::Unwrap(get<bound_indices>(storage->bound_args_))..., CallbackForward(unbound_args)...); } };
BindState<>
这存储了传递到Bind()中的所有状态,也是大多数模板解析发生的神奇地方。
Runnable是我们要绑定参数的仿函数。
RunType是Callback<>应该使用的Run()函数的类型。
通常,这与Runnable的RunType相同,但如果使用了IgnoreResult()这样的适配器,则可能有所不同。
BoundArgsType 包含使用函数类型的所有绑定参数的存储类型。
template <typename Runnable, typename RunType, typename BoundArgList> struct BindState; template <typename Runnable, typename R, typename... Args, typename... BoundArgs> struct BindState<Runnable, R(Args...), TypeList<BoundArgs...>> final : public BindStateBase { private: using StorageType = BindState<Runnable, R(Args...), TypeList<BoundArgs...>>; using RunnableType = Runnable; // true_type if Runnable is a method invocation and the first bound argument // is a WeakPtr. using IsWeakCall = IsWeakMethod<HasIsMethodTag<Runnable>::value, BoundArgs...>; using BoundIndices = MakeIndexSequence<sizeof...(BoundArgs)>; using Unwrappers = TypeList<UnwrapTraits<BoundArgs>...>; using UnboundForwardArgs = DropTypeListItem< sizeof...(BoundArgs), TypeList<typename CallbackParamTraits<Args>::ForwardType...>>; using UnboundForwardRunType = MakeFunctionType<R, UnboundForwardArgs>; using InvokeHelperArgs = ConcatTypeLists< TypeList<typename UnwrapTraits<BoundArgs>::ForwardType...>, UnboundForwardArgs>; using InvokeHelperType = InvokeHelper<IsWeakCall::value, R, Runnable, InvokeHelperArgs>; using UnboundArgs = DropTypeListItem<sizeof...(BoundArgs), TypeList<Args...>>; public: using InvokerType = Invoker<BoundIndices, StorageType, Unwrappers, InvokeHelperType, UnboundForwardRunType>; using UnboundRunType = MakeFunctionType<R, UnboundArgs>; BindState(const Runnable& runnable, const BoundArgs&... bound_args) : BindStateBase(&Destroy), runnable_(runnable), ref_(bound_args...), bound_args_(bound_args...) {} RunnableType runnable_; MaybeScopedRefPtr<HasIsMethodTag<Runnable>::value, BoundArgs...> ref_; Tuple<BoundArgs...> bound_args_; private: ~BindState() {} static void Destroy(BindStateBase* self) { delete static_cast<BindState*>(self); } }; } // namespace internal } // namespace base
Document of callback.h in mojo
导言
——————
模板回调类是一个广义函数对象。与bind.h中的bind()函数一起,它们提供了一种类型安全的方法来执行函数的部分应用程序。部分应用程序(或“currying”)是将一个函数的参数的子集绑定到生成另一个需要较少参数的函数的过程。这可以用来传递一个延迟执行单元,就像其他语言中使用词法闭包一样。例如,在Chromium代码中使用它来调度不同MessageLoops上的任务。
无未绑定输入参数的回调(base::Callback
内存管理和传递
——————
回调对象本身应该通过常量引用(const-ref)传递,并通过复制进行存储。它们在内部通过一个有引用计数的类存储它们的状态,因此不需要删除。
通过常量引用传递的原因是为了避免不必要的AddRef/Release改变内部状态。
基础材料快速参考
——————
O 绑定普通函数
int Return5() { return 5; } base::Callback<int(void)> func_cb = base::Bind(&Return5); LOG(INFO) << func_cb.Run(); // Prints 5.
O 绑定一个类方法
第一个要绑定的参数是要调用的成员函数,第二个参数是要调用它的对象。
class Ref : public base::RefCountedThreadSafe<Ref> { public: int Foo() { return 3; } void PrintBye() { LOG(INFO) << "bye."; } }; scoped_refptr<Ref> ref = new Ref(); base::Callback<void(void)> ref_cb = base::Bind(&Ref::Foo, ref); LOG(INFO) << ref_cb.Run(); // Prints out 3.
默认情况下,对象必须支持RefCounted,否则将出现编译器错误。如果在线程之间传递,请确保它是RefCountedThreadSafe!如果您不想使用引用计数,请参阅下面的“成员函数的高级绑定”。
O 运行回调
可以使用其“Run”方法运行回调,该方法具有与回调的模板参数相同的特征。
void DoSomething(const base::Callback<void(int, std::string)>& callback) { callback.Run(5, "hello"); }
回调可以多次运行(运行时不会删除或标记回调)。但是,使用base::Passed时不行(见下文)。
void DoSomething(const base::Callback<double(double)>& callback) { double myresult = callback.Run(3.14159); myresult += callback.Run(2.71828); }
O 传递未绑定的输入参数
在Run()运行回调时指定未绑定的参数。它们在回调模板类型中指定:
void MyFunc(int i, const std::string& str) {} base::Callback<void(int, const std::string&)> cb = base::Bind(&MyFunc); cb.Run(23, "hello, world");
O 绑定(Bound Parameters)输入参数。
当您将回调创建为BIND()的参数时,将指定绑定参数。
它们将被传递给函数,回调Run()的实际运行者看不到这些值,甚至不知道它正在调用的函数。
void MyFunc(int i, const std::string& str) {} base::Callback<void(void)> cb = base::Bind(&MyFunc, 23, "hello world"); cb.Run();
无未绑定输入参数的回调(base::Callback
base::Closure cb = base::Bind(&MyFunc, 23, "hello world");
调用成员函数时,绑定参数跟在对象指针之后。
base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world");
参数的部分绑定。
可以在创建回调时指定一些参数,在执行回调时指定其余参数。
void MyFunc(int i, const std::string& str) {} base::Callback<void(const std::string&)> cb = base::Bind(&MyFunc, 23); cb.Run("hello world");
调用函数时,首先是绑定参数,然后是未绑定参数。
高级绑定的快速参考
——————
O 用弱指针绑定类方法
base::Bind(&MyClass::Foo, GetWeakPtr());
如果对象已被销毁,则不会运行回调。
危险:弱指针不是线程安全的,所以在线程之间传递时不要使用它!
O 绑定类方法并手动进行生存期管理
base::Bind(&MyClass::Foo, base::Unretained(this));
这将禁用对象上的所有生存期管理。
您负责确保对象在调用时处于活动状态。
O 绑定一个类方法并让回调拥有这个类
MyClass* myclass = new MyClass; base::Bind(&MyClass::Foo, base::Owned(myclass));
当回调被销毁时,该对象将被删除,即使它没有运行(如在关闭期间发布任务)。可能对“Fire & Forgot”的情况有用。
O 忽略返回值
有时,您希望调用一个函数,不希望该函数在回调中返回一个值。
int DoSomething(int arg) { cout << arg << endl; } base::Callback<void<int>) cb = base::Bind(base::IgnoreResult(&DoSomething));
绑定参数到Bind()的快速参考
——————
O 绑定参数被指定为Bind()的参数,并传递给函数
没有参数或没有未绑定参数的回调称为闭包(base::Callback
O 传递回调所拥有的参数
void Foo(int* arg) { cout << *arg << endl; } int* pn = new int(1); base::Closure foo_callback = base::Bind(&foo, base::Owned(pn));
该参数将在回调被销毁时被删除,即使它未运行(如在关闭期间发布task)。
O 作为作用域_ptr传递参数
void TakesOwnership(scoped_ptr<Foo> arg) {} scoped_ptr<Foo> f(new Foo); // f becomes null during the following call. base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f));
参数的所有权将与回调一起使用,直到将所有权传递给回调函数时才会运行它。这意味着回调只能运行一次。如果回调从未运行过,它将在销毁对象时将其删除。
O 将参数作为scpoed_refptr传递
void TakesOneRef(scoped_refptr<Foo> arg) {} scoped_refptr<Foo> f(new Foo) base::Closure cb = base::Bind(&TakesOneRef, f);
这应该“就行了”。只要闭包还活着,它就会接受一个引用,被调用函数的另一个引用也会被接受。
O 通过引用传递参数
除非使用ConstRef,否则常量引用将被*复制*。
举例:
void foo(const int& arg) { printf("%d %pn", arg, &arg); } int n = 1; base::Closure has_copy = base::Bind(&foo, n); base::Closure has_ref = base::Bind(&foo, base::ConstRef(n)); n = 2; foo(n); // Prints "2 0xaaaaaaaaaaaa" has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb" has_ref.Run(); // Prints "2 0xaaaaaaaaaaaa"
一般情况下,参数会复制到闭包中。危险:ConstRef在这里会存储一个const引用,并引用原始参数。这意味着您必须确保对象在回调完成前仍然存活!
实施说明
——————
此设计来自何处:
设计回调和绑定思想受到C++的tr1::function/tr1::bin和Google内部使用的“Google回调”系统的影响。
实施是如何工作的:
该系统有三个主要组成部分:
1)回调类。
2)Bind()函数。
3)参数wrapper(例如,UnRetainted()和ConstRef())。
回调类表示泛型函数指针。在内部,它存储一段重新计算的状态,表示目标函数及其所有绑定参数。每个特化回调都有一个模板构造函数,它接受一个BindState<>*。
在构造函数的上下文中,此BindState<>*指针的静态类型唯一地标识它所代表的函数、它的所有绑定参数以及能够调用目标的Run()方法。
回调的构造函数接受具有完整静态类型的BindState<>*,并删除目标函数类型以及绑定参数的类型。
为此,它存储一个指向特定Run()函数的指针,并将BindState<>*的状态转换为BindStateBase*。
只要这个BindStateBase*指针只与存储的Run()指针一起使用,就是安全的。
对于BindState<>*,对象是在Bind()函数中创建的。这些函数,以及一组内部模板负责下列工作:
-将函数特征(Function signature)展开为返回类型和参数。
-确定绑定的参数数量。
-创建存储绑定参数的BindState。
-执行编译时断言以避免容易出错的行为。
-返回一个Callback<>,该回调与未绑定参数的数量匹配,并且如果我们绑定一个方法,它知道目标对象的正确的refcounting 语义。
绑定函数使用类型推断和特化模板来完成上述工作。默认情况下,Bind()将存储所有绑定参数的副本,如果绑定的函数是类方法,则尝试refcount 目标对象。即使函数将参数作为常量引用,也会创建这些副本。(禁止绑定到非const引用,请参见bind.h)。
为了改变这一行为,我们引入了一组参数包装器(例如 Unretained(), ConstRef())。这些是通过值传递的简单容器模板,并包装指向参数的指针。
有关更多信息,请参见base/bind_helpass.h中的文件级注释。
这些类型将分别传递给Unwrap()函数和MaybeRefcount()函数以修改Bind()的行为。Unwrap()和MaybeRefcount()函数通过根据参数是否是wrapper类型执行部分特化来更改行为。
ConstRef()类似于tr1::cref。“Unretained”()是Chromium所特有的。
为什么不使用TR1函数/BIND?
曾经考虑过直接使用tr1::function和tr1::bind,但由于在构造期间绑定参数和在调用期间转发参数所涉及的复制构造函数调用的数量而最终被拒绝。
这些拷贝在C++0x中不再是一个问题,因为C++0x将支持rvalue引用,允许编译器避免这些拷贝。但是,等待C++0x不是一个选项。
在GCC版本4.4.3(Ubuntu4.4.3-4ubuntu5)上使用valgrind进行测量时,tr1::bind调用本身将为每个绑定参数调用三次非简单的复制构造函数。
此外,每次传递tr1::function时,都会再次复制每个绑定参数。除了在绑定和调用时获取的副本外,复制tr1::function还会导致复制所有绑定参数和状态。此外,在Chromium中,在表示类方法调用时,回调需要对目标对象进行引用。这不受tr1支持。
最后,tr1::function和tr1::bind有一个更通用、更灵活的API。
这包括使用tr1::bind::placeholder对参数重新排序、对非Const引用参数的支持以及tr1::function对象的一些有限的子类型(例如,tr1::function
其中的一些,例如允许引用参数和函数的子类型化,实际上可能会成为错误的来源。删除对这些特性的支持实际上允许更简单的实现和更精确的API。
为什么不用Google Callback呢?
Google回调系统也不支持重新计算。此外,在参数的类型转换方面,它的实现有一些奇怪的边缘情况。特别是,参数的恒定性有时必须与函数特征完全匹配,否则类型推断可能会中断。
鉴于上述情况,编写一个定制的解决方案就更容易了。
目前还缺少的功能:
-调用Bind的返回值,即bind(&foo).Run()不起作用;
-将数组绑定到接受非常量指针的函数。
举例:
void Foo(const char* ptr); void Bar(char* ptr); Bind(&Foo, "test"); Bind(&Bar, "test"); // This fails because ptr is not const.
——————————————
头文件声明:
namespace base {
首先,我们向前声明回调类模板。这将通知编译器,模板只有1个类型参数,这是回调所表示的函数特征。之后,为0-7个参数创建特化模板。
注意,即使模板类型列表增加了,特化仍然只有一个类型:函数特征(Function signature)。
如果您正在考虑在您自己的头文件中向前声明回调,请改为包含“base/Callback_Forward.h”。
template <typename Sig> class Callback; namespace internal { template <typename Runnable, typename RunType, typename BoundArgsType> struct BindState; } // namespace internal template <typename R, typename... Args> class Callback<R(Args...)> : public internal::CallbackBase { public: typedef R(RunType)(Args...); Callback() : CallbackBase(NULL) { }
请注意,此构造函数不能是显式的,而且bind()不能返回确切的Callback<>类型。
有关详细信息,请参见base/bind.h。
template <typename Runnable, typename BindRunType, typename BoundArgsType> Callback(internal::BindState<Runnable, BindRunType, BoundArgsType>* bind_state) : CallbackBase(bind_state) {
强制将赋值赋给Polymoric Invoke的局部变量,这样编译器将检查传入的run()方法是否具有正确的类型。
PolymorphicInvoke invoke_func = &internal::BindState<Runnable, BindRunType, BoundArgsType> ::InvokerType::Run; polymorphic_invoke_ = reinterpret_cast<InvokeFuncStorage>(invoke_func); } bool Equals(const Callback& other) const { return CallbackBase::Equals(other); } R Run(typename internal::CallbackParamTraits<Args>::ForwardType... args) const { PolymorphicInvoke f = reinterpret_cast<PolymorphicInvoke>(polymorphic_invoke_); return f(bind_state_.get(), internal::CallbackForward(args)...); } private: typedef R(*PolymorphicInvoke)( internal::BindStateBase*, typename internal::CallbackParamTraits<Args>::ForwardType...); };
语法糖,使Callback
typedef Callback<void(void)> Closure; } // namespace base