11

C++11 では、ラムダ式を引数として取る関数をどのように宣言しますか? ラムダを宣言したり、テンプレート パラメーターとして受け取ったりするためのリソースをオンラインでたくさん見つけることができますが、私が本当にやりたいことは、クロージャーによって可能になるのと同様に、宣言が簡単なコールバック ハンドラーとしてラムダを利用できるようにすることです。 JavaScript と Objective-C のコード ブロックで。

基本的に、ラムダに置き換えたい古典的な C++ 構造は次のようなものです。

class MyCallback {
public:
    virtual ~MyCallback() {}
    virtual void operator(int arg) = 0;
};

void registerCallback(const std::shared_ptr<MyCallback> &);

void foo(void) {
    int a, b, c;
    class LocalCallback: public MyCallback {
        int a, b, c;
    public:
        LocalCallback(int a, int b, int c): a(a), b(b), c(c) {}
        void operator(int arg) { std::cout << (a+b+c)*arg << std::endl; }
    };
    registerCallback(std::shared_ptr<MyCallback>(new LocalCallback(a,b,c)));
}

これは次のように簡略化されます。

void registerCallback(/* WHAT GOES HERE? */);

void foo(void) {
    int a, b, c;
    registerCallback([=](int arg){std::cout << (a+b+c)*arg << std::endl; })
}

それで、私が書いたところはどうなり/* WHAT GOES HERE? */ますか?

編集:これは、すぐに消費されて呼び出されるのではなく、後でコールバックされるようにコールバックを格納するためのものです。

4

3 に答える 3

19

通常const std::function<void(int)> &またはstd::function<void(int)>.

std::functionconst参照または値で渡す必要があるかどうかについての評決が何であるかはわかりません。特に、とにかくコピーして保存するので、おそらく値で問題ありません。

すべての構文の途中で明確でない場合、void(int)は関数型であり、std::function<T>おおよそ「型 T の関数と同じ署名を持つファンクター」を意味します。

ラムダ自体には匿名型があります。ラムダ式の型に名前を付ける方法はなく、同じシグネチャを持つ異なるラムダ式の型は異なります。

auto foo = [=](int arg){std::cout << (a+b+c)*arg << std::endl; };
auto bar = [=](int arg){std::cout << (a+b+c)*arg << std::endl; };
// foo and bar have different types, accessible as decltype(foo), decltype(bar)

したがって、std::function基本的に同じシグネチャを持つ異なるファンクターを共通の型にまとめる型消去ラッパーである が必要です。これは、テンプレートを使用した静的ポリモーフィズムと、コールバックを登録して後で使用するために保存し、元の型を「記憶」せずに呼び出す場合に必要な動的ポリモーフィズムとの間の架け橋です。

于 2012-05-23T20:18:24.070 に答える
7
void registerCallback(const std::function<void(int)>& callback);
于 2012-05-23T20:16:33.753 に答える
5

関数テンプレートの使用を検討してください。過負荷時の動作の改善など、さまざまな理由があります(過負荷std::functionは苦痛です)。

template<typename Functor>
void registerCallback(Functor&& functor);

(パラメーターをとして受け入れることもできますがFunctor functor、それほど重要ではありません。)

functorコードが後で保存する必要がある場合、それはおそらく内に保持されますstd::function。避けたいstd::functionのは関数パラメーターです。

于 2012-05-23T21:31:04.030 に答える