基于C++11的call wrapper
要在C++中应用AOP,不像在其他的基于解释器的语言中那么方便,作为一种静态语言,如果给函数或者类的方法造一个wrapper,在wrapper里面嵌入调用前的代码和调用后的代码,也能达到一定程度的代码织入的效果。在C++11之前,要给一个函数或者方法做个能返回调用结果的wrapper并不简单,会比较复杂,而在C++11里面可以使用function模版,以及函数返回类型的推定,通过生成一个内嵌类的对象的构造函数来执行before动作,析构函数来实现after动作,而具体的before和action动作则可以通过lambda活着函数来表示,这样子实现起来就容易很多了,而且还可以设定一个对象给before/after动作作参数。
先看看函数的wrapper:
template<typename T, typename Probe> struct Wrapper<T*, Probe>{ typedef function<void(Probe)> WrapFuncType; T* _func; Probe _probe; WrapFuncType _after, _before; struct WrapInternal{ Wrapper<T*, Probe>* _wrapper; WrapInternal(Wrapper<T*,Probe>* w) : _wrapper(w){ _wrapper->_before( _wrapper->_probe ); } ~WrapInternal(){ _wrapper->_after( _wrapper->_probe ); } }; Wrapper(T* func, Probe p, WrapFuncType callBefore = [](Probe p){}, WrapFuncType callAfter = [](Probe p){}) : _probe(p){ _func = func;
_after = callAfter; _before = callBefore; } template<typename ...Args> auto operator()(Args && ...args) ->decltype( (*_func)(args...) ){ WrapInternal _w(this); return (*_func)(args...); } };
这个 wrapper 能够包裹一个函数,生成的对象的调用也像原来的函数的调用一样调用:
int foo_int(int a) { cout << "foo_int: " << a << endl; return a * a; }
......
typedef Wrapper<int(*)(int), int> T1; T1 w4(&foo_int, 100, [](int v){ cout << "w4<100> before" << endl; }, [](int v){ cout << "w4<100> after" << endl; }); cout << w4(400) << endl;
如果要给一个类方法做个wrapper,则可以按照如下方法:
template<typename T, typename Object, typename Probe> struct Wrapper<T, Object, Probe>{ typedef function<void(Probe)> WrapFuncType; T _method; Object _obj; Probe _probe; WrapFuncType _after, _before; struct WrapInternal{ Wrapper<T, Object, Probe>* _wrapper; WrapInternal(Wrapper<T, Object, Probe>* w) : _wrapper(w){ _wrapper->_before( _wrapper->_probe ); } ~WrapInternal(){ _wrapper->_after( _wrapper->_probe ); } }; Wrapper(T&& method, Object&& obj, Probe p, WrapFuncType callBefore = [](Probe p){}, WrapFuncType callAfter = [](Probe p){} ) : _probe(p){ _method = method; _obj = obj; _after = callAfter; _before = callBefore; } template<typename ...Args> auto operator()(Args && ...args) ->decltype(bind(_method, _obj, args...)(args...)) { WrapInternal _w( this ); auto b = bind(_method, _obj, args...); return b(args...); } };
使用的时候,设置好类名、对象、和方法:
struct Foo{ Foo(){ cout << "Foo::Foo" << endl; } void bar(int v){ cout << "Foo::bar " << v << endl; } };
......
typedef Wrapper<void(Foo::*)(int), Foo*, const char*> T2; Foo f; T2 w5(&Foo::bar, &f, "method", [](const char* v){ cout << "w5<method> before" << endl;}, [](const char* v){ cout << "w5<method> after" << endl;}); w5(500);
通过这2种方法生成的wrapper对象还可以当作函数一样再次套上一个wrapper,也就是通过这种方法可以实现多个层次嵌套的wrapper,调用的时候从外到里的次序调用before动作,执行完原函数或者方法之后,再按照从里到外的次序调用after动作,最后返回原函数或者方法的返回值。
访问 https://github.com/icandroid/wrapper11 可以查看这个 wrapper 的源代码和演示例子。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。