C++で関数を合成する

関数 - ウォークスルー Haskell
Haskellには関数を入れ子にしなくてもいい$演算子がある。 そのまま引用する。

関数適用のときに便利な $ 演算子を紹介しましょう. この演算子は関数適用の区切りに用いられ,カッコの多くなった式を読みやすくします. 次の 2 つの式はそれぞれ同じ意味となります. haskell square (double (2 * 4)) -- 値: 256 square $ double $ 2 * 4 -- 値: 256

C++でも似たようなことができるといいのだが、例えば以下のような時にはうまくいかない。 operator+で関数を合成するときに、fとgの型が明らかになっていないといけないからだ(多分)。

auto g(int){...};
auto g(double){...};
auto h = f + g;//+はうまいこと実装したとする
h(5);

一応以下のような形でgがどんな型なのかを明らかにして手動で多重定義を解決するようなことをすれば動くようだが、そんなことはできればしたくない。

auto h = f + static_cast<decltype(g(std::declval<double>()))(*)(double)>(g);

もう一つの解決方法は、関数gが必要になるタイミングをずらせばいい。 遅延評価と呼ばれるものだ。具体的にはラムダλgでgを包んで、fとλgに+を適用する。

[=](auto&&...args){return g(std::forward<decltype(args)>(args) );}

遅延評価 - Wikipedia

wandbox.org

何かできそうで面白い。

エラー文が悲惨になることが想像できるので、可能なら何らかの形で+が受け取るFとGに制限をかけてしまいたいのだけど、どうやって制限されるべきか否かを区別すればいいのかちょっとわからない。 invokable使うのだろうか。難しいな。