私はGCC6とそのコンセプトの実装を試しています。私はHaskell Preludeが実験のための良いソースであると考えました。ハスケルの中心的な機能の1つは関数の構成であり、これは私が直ちに取り組む必要があったものです。呼び出し可能な引数を知る前に、怠惰なコンポジションを制約するにはどうすればよいですか?
template <typename F, typename G>
auto operator*(F f, G g)
{
return [f, g](auto... args) {
return f(g(args...));
}
}
素晴らしい作品と私は同じようなものを行うことができます:私は、私はこの関数を書いたことが最高のようにHaskellの構文模倣
auto add([](int a, int b) { return a + b; }
auto doubled([](int a) { return a * 2; }
auto add_then_double(doubled * add);
assert(add_then_double(2, 3) == 10);
幸せは、私が行くことにしました私の機能構成にいくつかの制約を適用しましたが、私はすぐにその怠惰のために問題にぶつかりました。
まず私はこのコンセプトを書いた:私はAndrew Sutton's origin githubのプロジェクトで見つかった概念のオフに基づいて
template <typename F, typename Ret, typename... Args>
concept bool Function()
{
return requires(F f, Args ...args) {
{ f(args...) } -> Ret;
}
}
。
私は元の機能に適用しようとしました。私が持っている問題は、G
がどんな引数がG
に渡されるのかわからずに何が返ってくるのかわからないということです。G
を拘束することができず、何が与えられているのかわからずに何を返すのか分かりません。それは私が何をG
返すかわからないので知っている。
は返信の種類に関係なく、F
が返すものを気にしない新しいFunction
というコンセプトが必要であると私は確信しています。そして、私はパラメータがタイプし、GとそれゆえFのために修正する内側のラムダに制約を置くことができたと思うが、これは私が構成できない関数を構成することができ、コールサイトまでエラーを取得しないことを意味します。これは避けられますか?
たぶん、このような何か:(私もそれを行うことができる場合)
template <typename F, typename G>
auto operator*(F f, G g)
{
return [f, g](auto... args)
// is it even possible to constrain here?
requires FunctionAnyReturn<G, decltype(args)...>
&& FunctionAnyReturn<F, decltype(G(decltype(args)...))>
{
return f(g(args...));
}
}
が、これは私ができる最善のですか?
おかげええ、これは解決策のように見えます。私は概念的なエラーなしに2つの非呼び出し可能なオブジェクトを作成できるという事実が気に入らないので、残念です。とにかく、引数型を前もって必要としないCallableのコールバックを提供できるのですか? –
@SamKellett箱のままではありません。関数オブジェクトがその「署名」やそれに近いものを作る必要があるプロトコルを遵守することを選択できますが、それは明らかなメリットがない巨大な取り組みです。 –
公平、答えてくれてありがとう –