Loki之Funtion

阅读Loki中Funtion源码之后的个人理解,该库归纳起来可以说有三层(C++设计新思维列举到2个参数,此处列举到3个参数),要记住C++的模板其实就是C语言高级的宏定义,如果用户没有用到对应的模板编译器是不会生成对应代码的。

第一层:

    template <typename R, template <class, class> class ThreadingModel>
    class FunctorImpl<R, NullType, ThreadingModel>
        : public Private::FunctorImplBase<R, ThreadingModel>
    {
    public:
        typedef R ResultType;
        virtual R operator()() = 0;
    };

    ////////////////////////////////////////////////////////////////////////////////
// class template FunctorImpl
// Specialization for 1 parameter
////////////////////////////////////////////////////////////////////////////////

    template <typename R, typename P1, template <class, class> class ThreadingModel>
        class FunctorImpl<R, Seq<P1>, ThreadingModel>
        : public Private::FunctorImplBase<R, ThreadingModel>
    {
    public:
        typedef R ResultType;
        typedef typename TypeTraits<P1>::ParameterType Parm1;
        virtual R operator()(Parm1) = 0;
    };

////////////////////////////////////////////////////////////////////////////////
// class template FunctorImpl
// Specialization for 2 parameters
////////////////////////////////////////////////////////////////////////////////

    template <typename R, typename P1, typename P2,
        template <class, class> class ThreadingModel>
    class FunctorImpl<R, Seq<P1, P2>, ThreadingModel>
        : public Private::FunctorImplBase<R, ThreadingModel>
    {
    public:
        typedef R ResultType;
        typedef typename TypeTraits<P1>::ParameterType Parm1;
        typedef typename TypeTraits<P2>::ParameterType Parm2;
        virtual R operator()(Parm1, Parm2) = 0;
    };

对应的还有virtual R operator()(Parm1, Parm2, Pram3) = 0;  virtual R operator()(Parm1, Parm2, Pram3,Pram4...) = 0总共有15个参数为止;每个operator()操作符都是纯虚函数,这样上层类继承之实现多态。

需要注意的是每个模板特化的FunctorImpl只有一个R operator(),父类FunctorImplBase暂时不用关注

第二层:

template <class ParentFunctor, typename Fun>
    class FunctorHandler
        : public ParentFunctor::Impl
    {
        typedef typename ParentFunctor::Impl Base;
    private:        Fun f_;
    public:
        typedef typename Base::ResultType ResultType;
        typedef typename Base::Parm1 Parm1;
        typedef typename Base::Parm2 Parm2;
        typedef typename Base::Parm3 Parm3;
        typedef typename Base::Parm4 Parm4;
        typedef typename Base::Parm5 Parm5;
        typedef typename Base::Parm6 Parm6;
        typedef typename Base::Parm7 Parm7;
        typedef typename Base::Parm8 Parm8;
        typedef typename Base::Parm9 Parm9;
        typedef typename Base::Parm10 Parm10;
        typedef typename Base::Parm11 Parm11;
        typedef typename Base::Parm12 Parm12;
        typedef typename Base::Parm13 Parm13;
        typedef typename Base::Parm14 Parm14;
        typedef typename Base::Parm15 Parm15;

        FunctorHandler(const Fun& fun) : f_(fun) {}

        LOKI_DEFINE_CLONE_FUNCTORIMPL(FunctorHandler)

#ifdef LOKI_FUNCTORS_ARE_COMPARABLE

        bool operator==(const typename Base::FunctorImplBaseType& rhs) const
        {
            // there is no static information if Functor holds a member function
            // or a free function; this is the main difference to tr1::function
            if(typeid(*this) != typeid(rhs))
                return false; // cannot be equal

            const FunctorHandler& fh = static_cast<const FunctorHandler&>(rhs);
            // if this line gives a compiler error, you are using a function object.
            // you need to implement bool MyFnObj::operator == (const MyFnObj&) const;
            return  f_==fh.f_;
        }
#endif
        // operator() implementations for up to 15 arguments

        ResultType operator()()
        { return f_(); }

        ResultType operator()(Parm1 p1)
        { return f_(p1); }

        ResultType operator()(Parm1 p1, Parm2 p2)
        { return f_(p1, p2); }

        ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3)
        { return f_(p1, p2, p3); }    //后面还有operator()(Parm1 p1, Parm2 p2, Parm3 p3, Pram4 p4....)

FunctorHandler继承自模板参数ParentFunctor内部定义的类型Impl,待会看到第三层的时候就会发现其实是对应参数类型的FunctorImpl的某个特化版本,这样FunctorHandler实现了FunctorImpl中的重载operator()的虚函数,

而其中的成员Fun f_可能为函数指针或者函数对象,即用户传递进来的参数

第三层:

template <typename R = void, class TList = NullType,
        template<class, class> class ThreadingModel = LOKI_DEFAULT_THREADING_NO_OBJ_LEVEL>
    class Functor
    {

    private:        std::auto_ptr<Impl> spImpl_;
    public:
        // Handy type definitions for the body type
        typedef FunctorImpl<R, TList, ThreadingModel> Impl;
        typedef R ResultType;
        typedef TList ParmList;
        typedef typename Impl::Parm1 Parm1;
        typedef typename Impl::Parm2 Parm2;
        typedef typename Impl::Parm3 Parm3;
    //......

        // Member functions

        Functor() : spImpl_(0)
        {}

        Functor(const Functor& rhs) : spImpl_(Impl::Clone(rhs.spImpl_.get()))
        {}

        Functor(std::auto_ptr<Impl> spImpl) : spImpl_(spImpl)
        {}

        template <typename Fun>
        Functor(Fun fun)
        : spImpl_(new FunctorHandler<Functor, Fun>(fun))
        {}

        template <class PtrObj, typename MemFn>
        Functor(const PtrObj& p, MemFn memFn)
        : spImpl_(new MemFunHandler<Functor, PtrObj, MemFn>(p, memFn))
        {}

        ResultType operator()() const        {            LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL            return (*spImpl_)();         }

        ResultType operator()(Parm1 p1) const        {             LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL            return (*spImpl_)(p1);         }                ResultType operator()(Parm1 p1, Parm2 p2) const        {                LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL            return (*spImpl_)(p1, p2);         }                ResultType operator()(Parm1 p1, Parm2 p2, Parm3 p3) const        {                LOKI_FUNCTION_THROW_BAD_FUNCTION_CALL            return (*spImpl_)(p1, p2, p3);         }    //......

注意成员std::auto_ptr<Impl> spImpl_;其类型是FunctorImpl根据模板参数TList会选择对应的特化版本,它是FunctorHandler的基类,为什么这么说请看对应的构造函数就明白

        template <typename Fun>
        Functor(Fun fun)
        : spImpl_(new FunctorHandler<Functor, Fun>(fun))
        {}

该构造函数也是模板函数,模板参数fun是用户传递进来对应的函数指针或者仿函数,还记得FunctorHandler继承自Functor::Impl吗?这时候就是子类FunctorHandler赋值给基类指针spImpl实现了多态,当调用operator()时候转发的过程是

(*spImpl_)(...)

spImpl的operator()为虚函数转发给子类FunctorHandler的operator();FunctorHandler调用用户传递进来的函数指针或者仿函数

暂时写到这,后期完善

时间: 2024-10-06 15:42:45

Loki之Funtion的相关文章

[原创]loki库之内存池SmallObj

loki库之内存池SmallObj 介绍 loki库的内存池实现主要在文件smallobj中,顾名思义它的优势主要在小对象的分配与释放上,loki库是基于策略的方法实现的,简单的说就是把某个类通过模板参数传递给主类,比如某个对象的创建可以通过不同的创建策略进行创建,本文主要讲loki的大致实现. smallobj层次 loki.smallobj主要分四层: 应用层smallobject,重载了operator new 和operator delete,内存通过底层获取 内存分配smallobjA

Loki之ThreadPool

Loki中的ThreadPool目的主要是对创建出来的线程进行复用. ThreadPool在Test而非Loki目录下,因此并非是标准Loki的组件之一,不过我们可以对其修改定制, 下面是对其源码的大致分析,ThreadPool顾名思义线程池,一般我们使用线程的时候CreateThread调用我们的回调函数,当回调函数结束之后我们的线程也随之终结销毁,这样出现的问题是我们想执行一个多线程任务都要CreateThread,我们是否能够CreateThread调用我们的回调函数结束之后暂时将这个线程

C++设计模式类库 Loki介绍与用法

C++设计模式类库 Loki介绍与用法 Loki是由Andrei编写的一个与<Modern C++ Design>(C++设计新思维)一书配套发行的C++代码库.它不仅把C++模板的功能发挥到了极致,而且把类似设计模式这样思想层面的东西通过库来提供.本篇文章介绍如何利用Loki来轻松地实现一些设计模式. 由于Loki使用了大量牛X到爆的模板技巧,对编译器的要求是很苛刻的,官方兼容列表里只列出了VC7.1以上版本及GCC3.4以上版本.如果你象我一样喜欢用C++Builder6或VC6,可以去下

C++ 三大库boost、loki、stlport

C++ 三大库boost.loki.stlport 在C++中,库的地位是非常高的.C++之父 Bjarne Stroustrup先生多次表示了设计库来扩充功能要好过设计更多的语法的言论.现实中,C++的库门类繁多,解决的问题也是极其广泛,库从轻量级到重 量级的都有.不少都是让人眼界大开,亦或是望而生叹的思维杰作.由于库的数量非常庞大,而且限于笔者水平,其中很多并不了解.所以文中所提的一些库都是比较著名的大型库. 标准库 标准库中提供了C++程序的基本设施.虽然C++标准库随着C++标准折腾了许

JS funtion()中URL不跳转后台action问题

JS funtion()中URL不跳转后台action问题 今天遇到一个百思不得其解的问题,到现在解决了,但是仍然不知道所以然(估计是因为域名不一致导致的),记录一下 $.get(actionUrl, {"parentId":parentId}, function(objResult){ $("#childType").find("option").remove(); $("#childType").append('<o

[C++模板]Loki中的Length和TypeAt使用C++11特性改进

C++模板变参实现Loki中的Length和TypeAt 一,原Loki中的Length和TypeAt模拟实现如下 1,模板文件 /**********************************                                                              * * Author : szyu * * Date : 2017.1.7 * **************************************/ #ifndef 

解析Funtion()构造函数

函数定义方法多种  : 1function f(x){     (语句编制函数)       2  函数直接量直接生成                               3  Function()构造函数 return  x;                             var f=function(x){return x;}                          var f=new Function(){"x","return x;&quo

C++设计模式类库Loki介绍

Loki是由Andrei编写的一个与<Modern C++ Design>(C++设计新思维)一书配套发行的C++代码库.它不仅把C++模板的功能发挥到了极致,而且把类似设计模式这样思想层面的东西通过库来提供. 详细可以参考   1. http://blog.csdn.net/witch_soya/article/details/7612579   2. http://blog.csdn.net/zdy0_2004/article/details/40320577 3. http://www.

使用loki+ mtail + grafana + prometheus server分析应用问题

loki 是一个方便的类似prometheus 的log 系统,mtail 是一个方便的日志提取工具, 可以暴露为http 服务——支持导出prometheus metrics 环境准备 docker-compose 文件 version: "3" services:  nginx-log:    build: ./    ports:    - "8090:80"    - "3903:3903"    volumes:    - "