先日のリアクティブシーケンスに、filter()
メンバ関数を追加してみました。(map()
は難しいのでやめました)
#include <iostream> #include <functional> template <class T> class reactive_sequence { std::function<void(T)> f_; std::function<bool(T)> filterf_; public: template <class F> void foreach(F f) { f_ = f; } template <class Pred> reactive_sequence& filter(Pred pred) { filterf_ = pred; return *this; } template <class U> void reaction(const U& arg) { if (!filterf_ || filterf_(arg)) f_(arg); } }; struct Point { int x, y; Point(int x, int y) : x(x), y(y) {} }; reactive_sequence<Point> seq; void click_event(Point p) { seq.reaction(p); } void print_ln(Point p) { std::cout << p.x << ',' << p.y << std::endl; } int main() { // イベントが発生したときのハンドラ seq.filter([](Point p) { return p.x > 0 && p.y > 0; }) .foreach([](Point p) { print_ln(p); }); // イベント起動 click_event({2, 3}); }
出力:
2,3
実際のイベント処理(foreach)とフィルタ処理をリスト処理のように分けられるようになります。
ここでは、有効範囲内のクリック座標のみをイベント処理しています。
この他にも、イベントにエラーが渡される可能性があってそのエラーイベントを単に捨てるような場合は、フィルタで弾けばいいですね。音声処理なんかでも、特定の周波数(?)帯のみ扱うようなコードが、すっきりしそうです。