Policyをメンバ関数ポインタで
前はpolicyでやってたのだが,いちいちオブジェクトを作る作業が大仰すぎると感じた.
そこでメンバ関数ポインタを使ってみた.
#include <iostream> using namespace std; // 本来はどこかで定義されているものたち typedef int HWND; void MouseCapture(HWND){} void ReleaseCapture(){} HWND GetHWnd(){return 0;} // MouseCapture()と型を揃えるためのヘルパー関数 void ReleaseCaptureHelper(HWND){ReleaseCapture();} class mouse_event_logger { public: void on_left_button_down(){cout << "LeftButtonDown" << endl;} void on_left_button_up(){cout << "LeftButtonUp" << endl;} void on_right_button_down(){cout << "RightButtonDown" << endl;} void on_right_button_up(){cout << "RightButtonUp" << endl;} //... }; void f( void (*mouse_capture)(HWND), HWND hwnd, mouse_event_logger* logger, void (mouse_event_logger::*method)(), bool enabled) { mouse_capture(hwnd); if (enabled) (logger->*method)(); }; class context { bool enabled; mouse_event_logger logger; public: context() : enabled(false) {} void set_enabled(bool b) {enabled = b;} // 同じようなメソッドがたくさん出てくるのでまとめたいけれど // 型の違いではないからtemplateではうまくまとめられない? void on_left_button_down(HWND hwnd) { ::MouseCapture(hwnd); if (enabled) logger.on_left_button_down(); } void on_left_button_up() { ::ReleaseCapture(); if (enabled) logger.on_left_button_up(); } // こうか? void on_right_button_down(HWND hwnd) { f(::MouseCapture, hwnd, &logger, &mouse_event_logger::on_right_button_down, enabled); } void on_right_button_up() { f(::ReleaseCaptureHelper, 0, &logger, &mouse_event_logger::on_right_button_up, enabled); } }; int main() { context c; c.set_enabled(true); c.on_left_button_down(GetHWnd()); c.on_left_button_up(); c.on_right_button_down(GetHWnd()); c.on_right_button_up(); return 0; }
うーん,やっぱりf()の引数が謎すぎてうざい.
fをメンバ変数にすれば多少マシになるが,(mouse_event_logger::*method)()は消えない.
間違えた.このコードだとfをメンバ関数にしても何も変わらないや.実際のコードでは変わるのだけど.
どうしたら簡潔にわかりやすく重複なしに書けるのだろうか.
D言語ならdelegateとか,alias templateとtemplate mixinがあるのに〜.
調べてないからMouseCapture()とReleaseCapture()の型はもしかしたら正規のものとは違うかも><;