web-dev-qa-db-ja.com

ラムダ式をC ++ 11のクラスのフィールドとして保存するにはどうすればよいですか?

クライアントが[]() -> void {}のようなラムダ式をクラスのフィールドとして保存できるクラスを作成したいのですが、その方法がわかりません。 1つの答えはdecltypeを使用することを提案しました 、これは成功しませんでした。 ideone source link です。以下がソースと結果です。

#include <cstdio>
auto voidLambda = []()->void{};

class MyClass {
public:
     decltype(voidLambda) t;
     MyClass(decltype(voidLambda) t) { 
        this->t = t;
     }
};

int main() {
   MyClass([] {
      printf("hi");
   });
}

結果:

prog.cpp: In constructor 'MyClass::MyClass(<lambda()>)':
prog.cpp:3:79: error: no matching function for call to '<lambda()>::__lambda0()'
prog.cpp:2:20: note: candidates are: <lambda()>::<lambda>(const<lambda()>&)
prog.cpp:2:20: note:                 <lambda()>::<lambda>(<lambda()>&&)
prog.cpp:3:88: error: no match for 'operator=' in '((MyClass*)this)->MyClass::t = t'
prog.cpp: In function 'int main()':
prog.cpp:5:27: error: no matching function for call to 'MyClass::MyClass(main()::<lambda()>)'
prog.cpp:3:48: note: candidates are: MyClass::MyClass(<lambda()>)
prog.cpp:3:14: note:                 MyClass::MyClass(const MyClass&)

誰もこれを行う方法を知っていますか?

44
user34537

クラスメンバをラムダ式にする場合は、呼び出し可能な関数を保持できる_std::function<>_ラッパー型(_<functional>_ヘッダーから)の使用を検討してください。例えば:

_std::function<int()> myFunction = []() { return 0; }
myFunction(); // Returns 0;
_

この方法では、ラムダ式のタイプを知る必要はありません。適切な関数タイプの_std::function<>_を保存するだけで、テンプレートシステムがすべてのタイプを処理します。より一般的には、適切な署名の呼び出し可能エンティティは、そのファンクターの実際の型が匿名(ラムダの場合)または非常に複雑な場合でも、_std::function<>_に割り当てることができます。

_std::function_テンプレート内の型は、保存する関数に対応する関数型でなければなりません。したがって、たとえば、2つのintsを取り込んでvoidを返す関数を格納するには、std::function<void (int, int)>を作成します。パラメータを取らず、intを返す関数の場合、std::function<int()>を使用します。あなたの場合、パラメータを取らずvoidを返す関数が必要なので、次のようなものが必要です:

_class MyClass { 
public:
    std::function<void()> function;
    MyClass(std::function<void()> f) : function(f) {
        // Handled in initializer list
    }
};

int main() {
    MyClass([] {
        printf("hi")
    }) mc; // Should be just fine.
}
_

お役に立てれば!

48
templatetypedef

クラスにラムダを格納するために考えられる唯一の方法は、ヘルパーmake_関数でテンプレートを使用することです:

#include <cstdio>
#include <utility>

template<class Lambda>
class MyClass {
    Lambda _t;
public:
    MyClass(Lambda &&t) : _t(std::forward<Lambda>(t)) {
        _t();
    }
};

template<class Lambda>
MyClass<Lambda> make_myclass(Lambda &&t) {
    return { std::forward<Lambda>(t) };
}

int main() {
    make_myclass([] {
        printf("hi");
    });
}
9
cubuspl42