阅读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调用用户传递进来的函数指针或者仿函数

暂时写到这,后期完善

Loki之Funtion的更多相关文章

  1. C++三大库boost、loki、stlport

    转: STL是一个标准,各商家根据这个标准开发了各自的STL版本.而在这形形色色的STL版本中,SGI STL无疑是最引人瞩目的一个.这当然是因为这个STL产品系出名门,其设计和编写者名单中,Alex ...

  2. 使用c++11改写loki的TypeList

    最近看了C++11的一些特性,最感兴趣的是可变模板参数,自动类型推断和匿名函数. Loki中的TypeList,是需要递归定义的,并且需要一个NullType作为尾节点. 可变模板参数使得实现Type ...

  3. c++异常处理第四篇---不使用try catch语句,使用Loki::ScopeGuard

    转载:神奇的Loki::ScopeGuard 2011-07-05 12:52:05 分类: C/C++ 转载:http://blog.csdn.net/fangqu/article/details/ ...

  4. 【转】tars源码漫谈第1篇------tc_loki.h (牛逼哄哄的loki库)

    loki库是C++模板大牛Andrei写的, 里面大量运用模板的特性, 而tc_loki.h借用了loki库的部分代码, 形成了一个基本的文件tc_loki.h, 来看看: #ifndef __TC_ ...

  5. Oracle ERP Audit Funtion in R12.2.4

    M1 JOB NAME:  164839 TABLE NAME: WIP_REQUIREMENT_OPERATIONS Request name: AuditTrail Update Tables O ...

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

    loki 是一个方便的类似prometheus 的log 系统,mtail 是一个方便的日志提取工具, 可以暴露为http 服务——支持导出prometheus metrics 环境准备 docker ...

  7. 使用 loki grafana 分析nginx 请求日志

    loki 是类似prometheus 的log 可视化展示.收集系统,已经集成在grafana 6.0 版本中了 说明: 测试环境使用了docker-compose 运行 环境准备 docker-co ...

  8. loki grafana 团队开源的,类似Prometheus 的log 系统

    Prometheus 主要面向的是metrics,但是loki 是log,这样加上grafana 强大的可视化以及alert能力, 我们可以做好多事情,loki 的设计来源于Prometheus. 组 ...

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

    JS funtion()中URL不跳转后台action问题 今天遇到一个百思不得其解的问题,到现在解决了,但是仍然不知道所以然(估计是因为域名不一致导致的),记录一下 $.get(actionUrl, ...

随机推荐

  1. Hive入门笔记---2.hive函数大全

    Hive函数大全–完整版 现在虽然有很多SQL ON Hadoop的解决方案,像Spark SQL.Impala.Presto等等,但就目前来看,在基于Hadoop的大数据分析平台.数据仓库中,Hiv ...

  2. [Linux]gcc/libc/glibc

    转自:http://blog.csdn.net/weiwangchao_/article/details/16989713 1.gcc(gnu collect compiler)是一组编译工具的总称. ...

  3. am335x 内核频率 ddr3频率 电压调整

    由Makefile可知,SPL的入口在u-boot-2011.09-psp04.06.00.08\arch\arm\cpu\armv7\start.S中 SPL的功能无非是设置MPU的Clock.PL ...

  4. 同过增强Connection类[重写了close的方法]实现的从连接池取出连接并放回连接的简单的实现流程

    package tk.dong.connection.util; import java.io.IOException;import java.io.InputStream;import java.i ...

  5. 本机添加多个git仓库账号

    我们可能会需要在一台电脑上以不同的github账户去使用git,这时就需要去解决如何管理本机上的多个ssh key的问题了. 生成新ssh key 如果我们电脑上已经存在了一个ssh key,那么我们 ...

  6. C++ 运算符重载一(二元运算符重载)

    //二元运算符重载 #include<iostream> using namespace std; class Point { public: Point(int x,int y){ th ...

  7. Web项目的WEB-INF目录使用说明以及重定向与转发

    写这篇文章的原因是看到了Tomcat下面的Webapps下面的,就想看一下. 总结一下这篇文章的内容: WEB-INF下面的内容都是只能由服务器级别才能访问,客户端并不能访问.什么是客户端级别?什么是 ...

  8. OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言

    OGNL是Object-Graph Navigation Language的缩写,它是一种功能强大的表达式语言(ExpressionLanguage,简称为EL),通过它简单一致的表达式语法,可以存取 ...

  9. mysql -- 创建存储过程 往数据表中新增字段

    需求: 往某数据库的某个表中新增一个字段(若该字段已存在,则不做操作:若该字段不存在,则新增) 百度了n久,没有符合要求的例子,只有参考加自己琢磨,最终终于给弄出来了,以下是几个版本的更迭 第一版: ...

  10. css 五角星 (转)

    1.前言 之前做的好几个项目中,都会遇到打分,评分,点赞这样的需求,写了很多次,每次需要再写的时候,就会翻出之前写过的代码,然后copy过来.总觉得这样的话没有进步,没有把知识放进脑袋里,所以,自己花 ...