瘦身前后——兼谈C 语言进化[4]

2008-02-23 05:41:06来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折

boost采用的办法也是C 98唯一的办法,就是为不同参数个数的Signature进行特化:

template<typename R, typename T1>

class function<R(T1)>

{

R operator()(T1 a1);

};

template<typename R, typename T1, typename T2>

class function<R(T1, T2)>

{

R operator()(T1 a1, T2 a2);

};

template<typename R, typename T1, typename T2, typename T3>

class function<R(T1, T2, T3)>

{

R operator()(T1 a1, T2 a2, T3 a3);

};


… // 再写下去页宽不够了,打住…

  如此一共N(N由一个宏控制)个版本。

  这种做法有两个问题:一,函数的参数个数始终还是受限的,您作出N个特化版本,那么对N 1个参数的函数就没辙了。boost::tuple也是这个问题。二,代码重复。每个特化版本里面除了参数个数不同之外基本其他都是相同的;boost解决这个问题的办法是利用宏,宏本身的一大堆问题就不说了,您只要打开boost.function的主体实现代码就知道有多糟糕了,近一千行代码,其中涉及元编程和宏技巧无数,可读性能够说基本为0。好在这是个标准库(boost.function将加入tr1)不用您维护,假如是您自己写了用的库,恐怕除了您谁也别想动了。所以第二个问题其实就是可读性可维护性问题,用Matthew Wilson的说法就是可发现性和透明性的问题,这是个很严重的问题,许多C 现代库因为这个问题而遭到诟病。

  现在,让我们来看一看加入了variadic templates之后的C 09实现:

template<typename R, typename... Args>

struct invoker_base {

virtual R invoke(Args...) = 0;

virtual ~invoker_base() { }

};

template<typename F, typename R, typename... Args>

struct functor_invoker : public invoker_base<R, Args...>

{

explicit functor_invoker(F f) : f(f) { }

R invoke(Args... args) { return f(args...); }

private:

F f;

};

template<typename Signature>

class function;

template<typename R, typename... Args>

class function<R (Args...)>
{

public:

template<typename F>

function(F f) : invoker(0)

{

invoker = new functor_invoker<F, R, Args...>(f);

}
R operator()(Args... args) const
{

return invoker->invoke(args...);

}
private:

invoker_base<R, Args...>* invoker;

};

  整个核心实现就这些!一共才36行!加上析构函数拷贝构造函数等边角料一共也就70行!更重要的是,整个代码清楚无比,任何涉及到可变数目个模板参数的地方都由variadic templates代替。“Args…”恰如其分的表达了我们想要表达的意思——多个参数(数目不管)。和C 98的boost.function实现真是天壤之别!

[1] [2] [3] [4] [5]




标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇: 瘦身前后——兼谈C 语言进化[1]

下一篇: 瘦身前后——兼谈C 语言进化[2]

热门词条
热门标签