為了繼續寫某一篇自去年年中[1]開始寫,到現在還沒完工的文章,不得已,只好把其中一部分岔開來,另外開了這篇,以免太複雜。那篇文章之所以會拖這麼久,當然是因為斷斷續續地寫,以及其中的技術我尚未完全掌握的緣故啦。

言歸正傳,C++ 的 <functional> 的概念很好用,可是標準裡有提供的功能,實在是太少了,所以常常會發生,要兜卻兜不出來,只好退回去全部用迴圈重寫。碰到這樣的情形,又無法拋棄 C++ 的偏執的話,頗令人沮喪。所以有機會的話,最好還是自己把缺的東西刻一刻,累積下來,希望總有一天能夠快快樂樂用 C++,無憂無慮沒煩惱。

這裡介紹的 functor,正是最近為了那篇還沒寫完的文章而刻的一個 functor。設這個 functor 叫做 gg 要做的事情很簡單,就是把要傳給另外一個 functor f 的兩個參數先對調之後,再傳給 f。也就是說,本來是 f(lhs, rhs) 這樣子呼叫,透過 g,變成 f(rhs, lhs) 的呼叫方式。

概念很簡單,所以實做起來也很簡單,其實作與 helper function 如下:

template <class Op>class param_reverser : public binary_function<typename Op::second_argument_type,                                              typename Op::first_argument_type,                                              typename Op::result_type>{public:

    param_reverser(Op op)        : op_(op)    {    }

    typename Op::result_type    operator()(const typename Op::second_argument_type& lhs,               const typename Op::first_argument_type&  rhs) const    {        return op_(rhs, lhs);    }

private:

    Op op_;

}; // class param_reverser<>

template <class Op>param_reverser<Op> param_reverse(Op op){    return param_reverser<Op>(op);}

用以下的程式測試:

struct digits_printer : public binary_function<int, int, void>{    void operator()(int lhs, int rhs) const    {        cout << "  [" << lhs << ", " << rhs << "]";    }};

int main(){    cout << "Let's try (3, 4) => (4, 3) first." << endl;    param_reverse(digits_printer())(3, 4);    cout << endl;

    int xs[] = { 10, 11, };

    cout << "Without parameter reverse: 2 should be at the second position."         << endl;    for_each(        xs, xs + (sizeof(xs) / sizeof(xs[0])),        bind2nd(digits_printer(), 2)    );    cout << endl;

    cout << "With parameter reverse: 2 should be at the first position."         << endl;    for_each(        xs, xs + (sizeof(xs) / sizeof(xs[0])),        bind2nd(param_reverse(digits_printer()), 2)    );    cout << endl;

    return 0;} 

其執行結果如下:

SHELL> ./a.outLet's try (3, 4) => (4, 3) first.  [4, 3]Without parameter reverse: 2 should be at the second position.  [10, 2]  [11, 2]With parameter reverse: 2 should be at the first position.  [2, 10]  [2, 11]

耶,講完了,這麼快。好吧,我承認這篇只是為了要把程式碼另外列出來,以免那篇未完成的文章過長且失焦罷了。


  1. 西元 2005 年 6 月。