(作者はこちら)
まず第一に、プラエトリアンの答えは正しいですが、少し詳しく説明したいと思います。
このライブラリはまだ非常に実験的なものであり、私はまだドキュメントに取り組んでいることに注意してください。上記のドキュメントの現在の状態は wiki で見つけることができます。特にhttps://github.com/schlangster/cpp.react/wiki/User-Guide-%7C-Signalsは質問に関連しています。
より詳細な例を次に示します。
int calcVolume(int w, int h, int d) { return w*h*d; }
D::VarSignalT<int> width = D::MakeVar(1);
D::VarSignalT<int> height = D::MakeVar(2);
D::VarSignalT<int> depth = D::MakeVar(3);
D::SignalT<int> volume = MakeSignal(&calcVolume, width, height, depth);
Observe(volume, [] (int v) {
printf("volume changed to %d\n", v);
});
width.Set(10); // => volume changed to 60.
printf("volume: %d\n", volume.Value()); // short: volume()
これは一種のバインド (関数入力としてシグナルをバインドする) ですが、逆 std::bind と同じではありません。volume は関数オブジェクトではありません。特に、ボリュームは Value() を呼び出しても再計算されず、依存するシグナルの 1 つが変更されたときに再計算され、結果が保存され、Value() がそれを返します。したがって、基本的には、いくつかの追加機能 (冗長な更新なし、グリッチなし、オプションの暗黙的な並列化なし) を備えたプッシュ ベースの変更伝達です。
問題は、MakeSignal が一時的なシグナルやラムダと混合すると混乱することです。
// First create a temporary area signal, then use it as an argument for the volume signal
D::SignalT<int> volume = MakeSignal(
[] (int a, int d) { return a * d; },
MakeSignal(
[] (int w, int h) { return w * h; },
width, height),
depth);
そんなものは誰も読みたくないですよね?少なくとも私はしたくない。
そのため、依存関係を左に移動し、SignalList でラップする代替構文があります。
// Note: Not sure if I have already pushed this variant yet
D::SignalT<int> volume =
MakeSignalList(
MakeSignalList(width, height).Bind([] (int w, int h) { return w * h; }),
depth
).Bind([] (int a, int d) { return a * d; });
最後に、邪悪なカンマと ->* オーバーロードを使用します。
D::SignalT<int> volume =
(
(width, height) ->* [] (int w, int h) { return w * h; },
depth
)
->* [] (int area, int d) { return a * d; };
これに関する問題は、他の人が指摘しているように、初めて見た人は一体何が起こっているのか分からないということです.
一方、信号を関数に接続することは、このライブラリを使用する場合の非常に一般的なタスクです。それが何をするかがわかれば、->* バージョンはより簡潔になり、データフロー グラフを視覚化します (幅と高さから一時領域へのエッジ、領域と深さからボリュームへのエッジ)。