0

次のシグネチャを持つオーバーロード関数があります。

void Foo(const std::function<void(int     )> &func);
void Foo(const std::function<void(int, int)> &func);

そして、ラムダで Foo() を使用したい場合は、次のようにする必要があります。

Foo((std::function<void(int     )>) [] (int i       ) { /* do something */ });
Foo((std::function<void(int, int)>) [] (int i, int j) { /* do something */ });

どちらもあまりユーザーフレンドリーではありません。次のように、ラムダの前にキャスト "(std::function<...>)" を追加しなくても、関数を使用する方がはるかに簡単です。

    Foo([] (int i       ) { /* do something */ }); // executes the 1st Foo()
    Foo([] (int i, int j) { /* do something */ }); // executes the 2nd Foo()

したがって、引数としてラムダを受け入れ、ラムダを上記のシグネチャのいずれかに自動的にキャストする別のオーバーロードが必要です。これはどのように行うことができますか?それとも、そもそも可能ですか?

template <typename Function> void Foo(Function function) {
    // insert code here: should be something like
    //   - check the signature of the 'function'; and
    //   - call 'Foo()' corresponding to the signature
}

助けてください。

PS。私はVS2010を使用しています。

4

2 に答える 2

3

ラムダが変数をキャプチャしない場合 (つまり、変数で始まる場合)、それは[]関数ポインターに変換可能であり、次のFooように宣言できます。

void Foo(void(*func)(int));
void Foo(void(*func)(int, int));

バージョンを保持したい場合はstd::function、これらのバージョンをそのバージョンに転送できます。それらを個別に実装したくない場合は、可変個引数テンプレートがうまく機能すると思います。

template<class... Args>
void Foo(void(*func)(Args...)) {
    return std::function<void(Args...)>(func);
}

ラムダが変数をキャプチャする場合、それらは関数ポインターに変換できないため、それらをstd::function自分でラップする必要があります。

于 2013-04-09T05:41:38.013 に答える