13

問題

任意の数のファンクター オブジェクト、またはより一般的には呼び出し可能なオブジェクト (異なる型) を受け入れ、それらを内部データ構造に適用する関数を作成したいと考えています。この関数は、コード内のさまざまなポイントでさまざまな数のファンクターと共に使用されます。

1,2,3...などを受け入れるために別のバージョンを作成してコードを複製するのではなく、可変個引数テンプレートを使用することを考えました。

特にこれについてGoogleで何も見つけることができず、他の人が役立つと思うかもしれないので、回答として以下に投稿する解決策を見つけました。しかし、誰かがより良いアイデアを持っている場合は、投稿してください。これを行う標準的な方法があるはずだと感じていますか?

素朴な試み

これがうまくいかないことはわかっていましたが、最初の試みは

#include <iostream>
using namespace std;

struct FunctorA {
    void operator() () {
        cout << "FunctorA" << endl;
    }
};

struct FunctorB {
    void operator() () {
        cout << "FunctorB" << endl;
    }
};

template<typename... Fs>
void apply_functors(Fs... fs) {
     fs()...;   // will not work - can only expand packs in certain situations (e.g. as funciton 
}

int main(void) {
    apply_functors(FunctorA(),FunctorB());
    apply_functors(FunctorA());
    apply_functors([]()->void{ cout << "Lambda" << endl; });
    return 0;
}

ただし、特定の状況でのみパラメーター パックを拡張することが許可されており、このような無料のものはないため、これは機能しません。

試行 2

私の次のアイデアは、ファンクターをパラメーターとして渡して展開することしかできないダミー関数を作成することでした。この背後にある理由は、関数パラメーターは、パラメーター パックを拡張できる状況の 1 つだからです。

template<typename... Fs>
void _dummyF_impl(Fs... fs){}

template<typename... Fs>
void apply_functors(Fs... fs) {
    _dummyF_impl( fs()... );    // only works if all functors return a value (else we get "invalid use of 'void'")
}

ただし、ファンクターはoperator()s から void を返し、void をパラメーターとして関数に渡すことができないため、これは機能しません。

4

3 に答える 3

4

私の解決策

私が見つけた解決策はカンマ演算子でした。これまでこれを使用する理由はまったくありませんでしたが、ここではうまく収まります。

コンマ演算子は、個別のステートメントを評価するために使用できますが、最後の式の値を「返す」ため、 にa,b,c評価されcます。

したがって、これを使用してファンクターを評価し、void の戻り値を無視してから、 に渡される何かを返すことができます_dummyF_impl

template<typename... Fs>
void apply_functors(Fs... fs) {
   _dummyF_impl( (fs(),0)... );
}

これは g++ 4.7.3 で正常にコンパイルされ、実行すると出力は期待どおりになります。

FunctorB
FunctorA
FunctorA
Lambda
于 2013-08-06T10:13:32.850 に答える