1

ラムダ式を受け取るテンプレート化された関数がある場合、異なる数の引数を取るラムダ式で機能するように特殊化するにはどうすればよいですか? 次のコードが機能します。

template<typename Lambda>
void doSomething(Lambda callback)
{
    callback();
}

doSomething([] () { /* some code here */ } );

しかし、次のように呼び出すこともできるようにしたい場合:

doSomething([&foo] (int x)        { /* some code here */ } );
doSomething([&foo] (int x, int y) { /* some code here */ } );

doSomething() の特殊なバージョンを提供するために使用する構文は何ですか? この構文:

template<>
void doSomething<[] (int)>([] (int) callback)
{
    callback(3);
}

は Visual Studio 2012 でコンパイルされず、有効な構文がどのようになるかについての参照を見つけることができませんでした。出来ますか ?または、 doSomething() 内から、提供されたコールバックが受け取る引数の数を確認して、次のようなことができるようにすることは可能ですか?

template<typename Lambda>
void doSomething(Lambda callback)
{
    int numArgs = ???
    switch (numArgs) {
        case 0: callback();    break;
        case 1: callback(1);   break;
        case 2: callback(1,2); break;
    }
}
4

2 に答える 2

0

ラムダには、キャプチャしている場合とキャプチャしていない場合の 2 つのケースがあります。

最初のケースでは、(ラムダの から) ラムダの戻り値の型とパラメーターの型を抽出する必要があります。これについてoperator()は、この質問で説明します。

最後のケースでは、非キャプチャ ラムダには関数ポインター変換演算子があるため、関数ポインターの特殊化を使用できます。

関数に関してdoSomething()は、ここで行ったように、推定された引数の数に従ってファンクターを直接呼び出すことは不可能です。

template<typename Lambda>
void doSomething(Lambda callback)
{
    int numArgs = ???
    switch (numArgs)
    {
        case 0: callback();    break;
        case 1: callback(1);   break;
        case 2: callback(1,2); break;
    }
}

(必要な機能はstatic if、次の C++ 標準用に提案されています。 n3322およびn3329を参照してください)

特定の関数シグネチャに特化したヘルパー関数または構造体を使用する必要があります。何かのようなもの:

template<typename T> struct helper {};
template<typename R, typename P1>
struct helper<R(P1)>
{
    static R call(R (*lambda)(P1)) { return lambda(magic_param); }
};
template<typename R, typename P1, typename P2>
struct helper<R(P1,P2)>
{
    static R call(R(*lambda)(P1,P2)) { return lambda(magic_param_1,magic_param_2); }
};
// ...
template<typename R, typename... A>
void doSomething(R (*callback)(A...))
{
    helper<R(A...)>::call(callback);
}

どのようにパラメーター ( ) を生成しますmagic_param...か?

于 2012-11-08T23:25:36.507 に答える