瘦身前后——兼談C++語言進化(4)

字號:

(3)boost采用的辦法也是C++98的辦法,就是為不同參數(shù)個數(shù)的Signature進行特化:
    template
    class function
    {
    R operator()(T1 a1);
    };
    template
    class function
    {
    R operator()(T1 a1, T2 a2);
    };
    template
    class function
    {
    R operator()(T1 a1, T2 a2, T3 a3);
    };
    … // 再寫下去頁寬不夠了,打住…
    如此一共N(N由一個宏控制)個版本。
    這種做法有兩個問題:一,函數(shù)的參數(shù)個數(shù)始終還是受限的,你作出N個特化版本,那么對N+1個參數(shù)的函數(shù)就沒轍了。boost::tuple也是這個問題。二,代碼重復。每個特化版本里面除了參數(shù)個數(shù)不同之外基本其它都是相同的;boost解決這個問題的辦法是利用宏,宏本身的一大堆問題就不說了,你只要打開boost.function的主體實現(xiàn)代碼就知道有多糟糕了,近一千行代碼,其中涉及元編程和宏技巧無數(shù),可讀性可以說基本為0。好在這是個標準庫(boost.function將加入tr1)不用你維護,如果是你自己寫了用的庫,恐怕除了你誰也別想動了。所以第二個問題其實就是可讀性可維護性問題,用Matthew Wilson的說法就是可發(fā)現(xiàn)性和透明性的問題,這是一個很嚴重的問題,許多C++現(xiàn)代庫因為這個問題而遭到詬病。
    現(xiàn)在,讓我們來看一看加入了variadic templates之后的C++09實現(xiàn):
    template
    struct invoker_base {
    virtual R invoke(Args...) = 0;
    virtual ~invoker_base() { }
    };
    template
    struct functor_invoker : public invoker_base
    {
    explicit functor_invoker(F f) : f(f) { }
    R invoke(Args... args) { return f(args...); }
    private:
    F f;
    };
    template
    class function;
    template
    class function
    {
    public:
    template
    function(F f) : invoker(0)
    {
    invoker = new functor_invoker(f);
    }
    R operator()(Args... args) const
    {
    return invoker->invoke(args...);
    }
    private:
    invoker_base* invoker;
    };