...ing logging 4.0

はてなブログに移行しました。D言語の話とかいろいろ。

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()の型はもしかしたら正規のものとは違うかも><;