reference_closure
http://d.hatena.ne.jp/faith_and_brave/20080326/1206522694
http://d.hatena.ne.jp/Cryolite/20080325#p1
faith_and_braveさんの例を少し変えて、
#include <functional> #include <iostream> int main() { int count = 3; std::reference_closure<int(int)> f = [&](int x){ return x + (++count); }; std::cout << f(2) << std::endl; // 6 std::cout << f(2) << std::endl; // 7 }
というコードを考えます。
g++ 4.3.0の範囲でラムダ式を手動で書くとこんな感じになるはずです。
namespace hamigaki { namespace rc_detail { template<class... ArgTypes> struct reference_closure_base {}; template<class T1> struct reference_closure_base<T1> { typedef T1 argument_type; }; template<class T1, class T2> struct reference_closure_base<T1,T2> { typedef T1 first_argument_type; typedef T2 second_argument_type; }; } // namespace rc_detail template<class> class reference_closure; // undefined template<class R, class... ArgTypes> class reference_closure<R (ArgTypes...)> : public rc_detail::reference_closure_base<ArgTypes...> { public: typedef R result_type; reference_closure() {} R operator()(ArgTypes... args) const { return func_(frame_, args...); } protected: reference_closure(R (*f)(void*, ArgTypes...), void* p) : func_(f), frame_(p) { } private: R (*func_)(void*, ArgTypes...); // a function pointer void* frame_; // a static scope pointer reference_closure& operator=(const reference_closure&); // = delete }; } // namespace hamigaki #include <iostream> int main() { int count = 3; class F : public hamigaki::reference_closure<int (int)> { private: typedef hamigaki::reference_closure<int (int)> base_type; public: explicit F(void* frame) : base_type(&F::invoke, frame) , count(*(static_cast<int*>(frame) - 2)) // [ EBP - 8] { } F(F&& f) : base_type(static_cast<base_type&&>(f)) , count(f.count) { } int operator()(int x) const { return x + (++count); } private: int& count; static int invoke(void* frame, int x) { return F(frame)(x); } F& operator=(const F&); // = delete }; // __builtin_frame_address()はGCC拡張 hamigaki::reference_closure<int (int)> f(F(__builtin_frame_address(0))); std::cout << f(2) << std::endl; // 6 std::cout << f(2) << std::endl; // 7 }
nullptr関連は使えないので省略しています。
Fがreference_closureをpublic継承する必要性はないですね。
実装上はconvertibleで十分で、ムーブコンストラクタが面倒になっているだけです。