瘦身前后——兼談C++語言進(jìn)化(3)

字號(hào):

如果不想卷入C++ functional的噩夢(mèng)的話,你也可以這么寫:
    struct Op
    {
    int operator()(int a1, int a2) { return f(a1) + f(a2); }
    };
    transform(…, Op());
    稍微好一點(diǎn),但這種做法也有很嚴(yán)重的問題。
    為什么Java加入closure,其實(shí)還是一個(gè)語法問題。從嚴(yán)格意義上,Java的anonymous class已經(jīng)可以實(shí)現(xiàn)出一樣的功能了,正如C++的functor一樣。然而,代碼是給人看的,語言是給人用來寫代碼的,代碼的主要代價(jià)在維護(hù),維護(hù)則需要閱讀、理解。寫代碼的人不希望多花筆墨來寫那些自己本不關(guān)心的東西,讀代碼的人也希望“所讀即所表”,不想看到代碼里面有什么彎子,是自然語言自然抽象才好呢。
    所以,盡管closure是一顆語法糖,但卻是一顆很甜很甜的糖,因?yàn)橛辛薱losure你就可以寫:
    transform(…, <>(a1, a2){ f(a1) + f(a2) });
    Simple things should be simple!
    此外,closure大的好處還是在于對(duì)局部變量的方便的引用,設(shè)想我們想要?jiǎng)?chuàng)建的表達(dá)式是:
    int weight1 = 0.3, weight2 = 0.6;
    transform(…, f(_1)*weight1 + f(_2)*weight2);
    當(dāng)然,上面的語句是非法的,不過使用closure便可以寫成:
    int weight1 = 0.3, weight2 = 0.6;
    transform(…, <&>(_1, _2){ f(_1)*weight1 + f(_2)*weight2 } );
    用functor class來實(shí)現(xiàn)同樣的功能則要麻煩許多,一旦麻煩,就會(huì)error-prone,一旦error-prone,就會(huì)消耗人力,而人力,就是金錢。
    C++09也有希望加入lambda,不過這是另一個(gè)話題,下回再說。
    The Real Deal——variadic templates
    C++的callback類,google一下,沒有一打也有半打。其中尤數(shù)boost.function實(shí)現(xiàn)得最為靈活周到。然而,就在其靈活周到的接口下面,卻是讓人不忍卒讀的實(shí)現(xiàn);03年的時(shí)候我寫的第一篇boost源碼剖析就是boost.function的,當(dāng)時(shí)還覺得能看懂那樣的代碼牛得不行...話說回來,那篇文章主要剖析了兩個(gè)方面,一個(gè)是它對(duì)不同參數(shù)的函數(shù)類型是如何處理的,第二個(gè)是一個(gè)type-erase設(shè)施。其中第一個(gè)方面就占去了大部分的篇幅。
    簡(jiǎn)而言之,要實(shí)現(xiàn)一個(gè)泛型的callback類,就必須實(shí)現(xiàn)以下最常見的應(yīng)用場(chǎng)景:
    function caller = f;
    int r = caller(1, 2); // call f
    為此function類模板里面肯定要有一個(gè)operator(),然而,接下來,如何定義這個(gè)operator()就成了問題:
    template
    class function
    {
    operator()(???);
    };