任意の数の引数を受け入れるテンプレート関数foo()
があるとします。最後の引数が常にstd::function
である場合、CbArgs
にこのstd::function
のパラメータが含まれるように、以下に示すfoo()
テンプレートを実装するにはどうすればよいですか?テンプレート引数とstd ::関数パラメータの控除
std::function<void(int,int)> cb;
foo(5, "hello", cb);
私の最初のアイデアだった:
template<typename... InArgs, typename... CbArgs = ???>
// ^^^^^^^^^^^^
void foo(InArgs... args) { ... }
たとえば、次のように呼び出された場合CbArgs
は{int,int}
をする必要があります
template<typename... InArgs, typename... CbArgs>
void foo(InArgs... args, std::function<void(CbArgs...)>) { ... }
しかし、これはコンパイルされません:
note: template argument deduction/substitution failed:
note: mismatched types ‘std::function<void(CbArgs ...)>’ and ‘int’
foo(5, "hello", cb);
質問1:
なぜこれはコンパイルされませんか?なぜテンプレート引数の控除が失敗するのですか?
は最終的に、私はこのソリューションを思い付いた:ここ
template<typename... InArgs, typename... CbArgs>
void fooImpl(std::function<void(CbArgs...)>, InArgs... args) { ... }
template<typename... InArgs,
typename CbType = typename std::tuple_element_t<sizeof...(InArgs)-1, std::tuple<InArgs...>>>
void foo(InArgs... args)
{
fooImpl(CbType{}, args...);
}
CbType
はstd::function
あるInArgs
の最後のタイプです。その後、CbType
の一時的なものがfooImpl()
に渡されます。ここでCbArgs
が推測されます。これは動作しますが、私には醜いようです。
質問2:
は、私は2つの機能とCbType
の一時的なインスタンスを持つことなく、よりよい解決策があるかどうだろうか?
ですが、機能が最後の位置にある必要がありますか?または、最初の位置にすることができますか? – max66
最後の位置になければなりません。これは、最後の引数としてコールバックを持つ非同期関数をラップするために必要です。 – Kane
"する必要があります" - 私は申し訳ありませんが、私は最後の引数としてコールバックを持たない非同期関数を記述することができます。どのようにして、最後の引数としてコールバックが必要なのでしょうか?あなたはコンテンション・パス・スタイルを好むだけですか?あなたは「あなたがやっていること」の後に「次のことは起こる」と思っていますか?理由はたくさんありますが、「非同期関数は最後の引数としてコールバックを持たなければなりません」という理由をスキップし、結論を述べるだけです。 – Yakk