zoukankan      html  css  js  c++  java
  • 基于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 的源代码和演示例子。

  • 相关阅读:
    nodejs gulp如何获取参数
    nodejs 获取当前路径的方法
    gulp 如何排除文件和文件夹
    小技巧css解决移动端ios不兼容position:fixed属性,无需插件
    代码协议相关
    zen-coding
    directive 实例讲解
    angular api 地址
    一步一步搭建hibernate4+ spring+ struts2
    华为荣耀6 H60-L02/L12(联通版)救砖包【适用于无限重启】
  • 原文地址:https://www.cnblogs.com/raison/p/4532390.html
Copyright © 2011-2022 走看看