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

字號(hào):

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