Modern C++ Design 笔记 第五章 Generalized Functors

    说到Funtor呢,应该是STL中比较普遍使用的一个东西。大致的意思就是把一个类对象像函数一样的使用,当然这个类需要重载()操作符。因为他比较像函数,所以得了一个Funtor的名字,至于翻译好像主流的叫函数子??有点搞不清状况。
还是看一个最简单的Funtor的例子吧
  1. // test functor class
  2. template<class T> class plus
  3. {
  4. public:
  5.     void operator() (T& aa)
  6.     {
  7.         aa += 10;   
  8.     }
  9. };
  10. // test function
  11. template<class T> void c_print( const T& value)
  12. {
  13.     std::cout<<value<<std::endl;
  14. }
  15. int main (void)
  16. {
  17.         std::vector<int> v;
  18.         v.push_back(10);
  19.         v.push_back(11);
  20.         v.push_back(12);
  21.         for_each(v.begin(), v.end(), plus<int>());
  22.         for_each(v.begin(), v.end(), c_print<int>);
  23. }
这个可以看到的是Functor完成了函数一样的工作,但是同时也提供了一些便利的地方,代码符合C++的风格倒是真的。如果能想到的好处可能就是实际上模板函数和模板类的不同,比如我即使用函数,在有的情况的还是不罩的。我没有办法给一个模板函数偏特化,这种情况下当然类就要有优势了。但是没有什么绝对的。另外有些所谓调用性能上的提升,我不敢苟同。也同时觉得现代的应用程序的瓶颈定不在于此。我做了些比如std::sort中的less than的一些自己的实现,并没有发现所谓的雪崩效应,那个comparer functor和compare函数没有什么明显的性能上的差异。这时候的数量级已经到了100000。
    说的比较远了,还是回过来继续说这里的Functor的实现,这里的Functor的引出呢是源自与Command这种设计模式。这种模式有效的降低了invoker和receiver之间的联系。这种模式有图为证:
Modern C++ Design 笔记 第五章 Generalized Functors_第1张图片

而我们的Functor则成了实现这个Command或者说ConcreteCommand的利器。而且这个书层层递进的解说让人欲罢不能啊:)
首先看看最基本的实现:

  1. // Functor with any number and types of arguments
  2. template <typename ResultType, class TList>
  3. class Functor
  4. {
  5. ...
  6. };
可以看见的是这是第一步,就是了解模板的类型参数有哪些,通过字面意思可以理解的是明显的就是返回值和参数,返回值当然就是某个特定的类型ResultType而这个参数就又一次依赖了TypeList。有了这些定义呢,我们已经可以想象到完成之后的调用语句的形状了:) 类似于 Functor<double, TYPELIST_2(int, double)> myFunctor;
当然啦,为了多态等因素的考虑,实际的实现肯定不是这么简单,实际上是吧operate()的调用分发了一个叫FunctorImpl的类来完成的,这个类的定义基本上是这个样子的。
  1. template <typename R>
  2. class FunctorImpl<R, NullType>
  3. {
  4. public:
  5. virtual R operator()() = 0;
  6. virtual FunctorImpl* Clone() const = 0;
  7. virtual ~FunctorImpl() {}
  8. };
可以看到的是这里的operator()都是以虚函数的形式存在的。同时在Functor类里面的FunctorImpl我们引用了std::auto_prt这个智能指针:
  1. template <typename R, class TList>
  2. class Functor
  3. {
  4. public:
  5. ...
  6. Functor& operator=(const Functor&);
  7. explicit Functor(std::auto_ptr<Impl> spImpl);
  8. ...
  9. private:
  10. // Handy type definition for the body type
  11. typedef FunctorImpl<R, TList> Impl;
  12. std::auto_ptr<Impl> spImpl_;
  13. };
所以这个具体operator的实现呢应该就大致如下,每个functor的()调用实际上都是调用spImpl_对应的()操作符。
  1. operator()()
  2. {
  3. return (*spImpl_)();
  4. }
  5. operator()(Parm1 p1)
  6. {
  7. return (*spImpl_)(p1);
  8. }
其实到这里,基本上我们一个Functor template就完成的七七八八了。当然还有比这个更复杂的东西, 比如说传入的Functor参数不是一个类,而直接是一个函数,我们也应该可以完成调用,就像STL的那些函数一样。由此引来的问题还有如果是一个成员函数是不是也可以捏?好多的为什么:) 这个我们就偷懒一把,浅尝辄止了。。。



你可能感兴趣的:(Modern C++ Design 笔记 第五章 Generalized Functors)