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调用用户传递进来的函数指针或者仿函数
暂时写到这,后期完善
Loki之Funtion的更多相关文章
- C++三大库boost、loki、stlport
转: STL是一个标准,各商家根据这个标准开发了各自的STL版本.而在这形形色色的STL版本中,SGI STL无疑是最引人瞩目的一个.这当然是因为这个STL产品系出名门,其设计和编写者名单中,Alex ...
- 使用c++11改写loki的TypeList
最近看了C++11的一些特性,最感兴趣的是可变模板参数,自动类型推断和匿名函数. Loki中的TypeList,是需要递归定义的,并且需要一个NullType作为尾节点. 可变模板参数使得实现Type ...
- c++异常处理第四篇---不使用try catch语句,使用Loki::ScopeGuard
转载:神奇的Loki::ScopeGuard 2011-07-05 12:52:05 分类: C/C++ 转载:http://blog.csdn.net/fangqu/article/details/ ...
- 【转】tars源码漫谈第1篇------tc_loki.h (牛逼哄哄的loki库)
loki库是C++模板大牛Andrei写的, 里面大量运用模板的特性, 而tc_loki.h借用了loki库的部分代码, 形成了一个基本的文件tc_loki.h, 来看看: #ifndef __TC_ ...
- Oracle ERP Audit Funtion in R12.2.4
M1 JOB NAME: 164839 TABLE NAME: WIP_REQUIREMENT_OPERATIONS Request name: AuditTrail Update Tables O ...
- 使用loki+ mtail + grafana + prometheus server分析应用问题
loki 是一个方便的类似prometheus 的log 系统,mtail 是一个方便的日志提取工具, 可以暴露为http 服务——支持导出prometheus metrics 环境准备 docker ...
- 使用 loki grafana 分析nginx 请求日志
loki 是类似prometheus 的log 可视化展示.收集系统,已经集成在grafana 6.0 版本中了 说明: 测试环境使用了docker-compose 运行 环境准备 docker-co ...
- loki grafana 团队开源的,类似Prometheus 的log 系统
Prometheus 主要面向的是metrics,但是loki 是log,这样加上grafana 强大的可视化以及alert能力, 我们可以做好多事情,loki 的设计来源于Prometheus. 组 ...
- JS funtion()中URL不跳转后台action问题
JS funtion()中URL不跳转后台action问题 今天遇到一个百思不得其解的问题,到现在解决了,但是仍然不知道所以然(估计是因为域名不一致导致的),记录一下 $.get(actionUrl, ...
随机推荐
- C++的历史与现状
在31年前(1979年),一名刚获得博士学位的研究员,为了开发一个软件项目发明了一门新编程语言,该研究员名为Bjarne Stroustrup,该门语言则命名为——C with classes,四年后 ...
- Project Euler:Problem 34 Digit factorials
145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145. Find the sum of all numbers which are ...
- oracle初始操作
oracle登录 sqlplus sys/oracle as sysdba 这个登录之后呢 会出现这个: Connected to an idle instance. 这一步是连接上 [oracle ...
- JVM调优浅谈(转)
1.数据类型 java虚拟机中,数据类型可以分为两类:基本类型和引用类型.基本类型的变量保存原始值,即:它代表的值就是数值本身,而引用类型的变量保存引用值.“引用值”代表了某个对象的引用,而不是对象本 ...
- 微服务vs传统开发
使用微服务有一段时间了,这种开发模式和传统的开发模式对比,有很大的不同. 分工不同,以前我们可能是一个一个模块,现在可能是一人一个系统. 架构不同,服务的拆分是一个技术含量很高的问题,拆分是否合理对以 ...
- nginx报403错误的2种原因
- RabbitMQ用户角色及权限控制 -2
1.RabbitMQ的用户角色分类: none.management.policymaker.monitoring.administrator none 不能访问 management plugin ...
- css图标
一.介绍 采用这种字体,我们可以避免网站制作中采用好多图片,一方面解决了浏览器的兼容性问题.另一方面,这些字体都是矢量字体,我们只要在调整这些图标时,将他们的字体大小以及颜色,我们就可以解决很多不是图 ...
- Android API Guides---Bluetooth
Bluetooth Android平台包含蓝牙网络协议栈,它同意设备以无线方式与其他蓝牙设备进行数据交换的支持.应用程序框架提供了訪问通过Android蓝牙API的蓝牙功能.这些API使应用程序无线方 ...
- php如何互换一个数组的首尾元素 中间不变 首尾互换
群里有人提出一个问题 如何互换一个数组的首尾元素 中间不变 首尾互换 代码如下: <?php $array=array(1,2,3,4,5,6,7,8,9,10); $first=array_s ...