web-dev-qa-db-ja.com

Visual Studio 11でメンバー関数をstd :: functionに直接バインドする方法は?

メンバー関数をstd::functionに簡単にバインドするには、キャプチャー句を使用してラムダ式でそれらをラップします。

class Class
{
    Class()
    {
        Register([=](int n){ Function(n); });
    }

    void Register(std::function<void(int)> Callback)
    {

    }

    void Function(int Number)
    {

    }
};

ただし、次のように直接バインドしたいと思います。

// ...
Register(&Class::Function);
// ...

C++ 11標準によれば、これはサポートされるはずです。ただし、Visual Studio 11では、これらのコンパイラエラーが発生します。

エラーC2440: 'newline': 'int'から 'Class *'に変換できません

エラーC2647: '。*': 'int'で 'void(__thiscall Class :: *)(int)'を逆参照できません

22
danijar

C++ 11標準によれば、これはサポートされるべきだと思います

実はそうではありません。非静的メンバー関数には、タイプ(cv修飾)_YourType*_の暗黙の最初のパラメーターがあるため、この場合はvoid(int)と一致しません。したがって、 _std::bind_ の必要性:

_Register(std::bind(&Class::Function, PointerToSomeInstanceOfClass, _1));
_

例えば

_Class c;
using namespace std::placeholders; // for _1, _2 etc.
c.Register(std::bind(&Class::Function, &c, _1));
_

Editこれは同じClassインスタンスを使用して呼び出されることになります。その場合、単純な非メンバー関数を使用できます。

_void foo(int n)
{
  theClassInstance.Function(n);
}
_

その後

_Class c;
c.Register(foo);
_
38
juanchopanza

Stephan T. Lavavejによると-「bind()の使用を避け、...、ラムダを使用する」。 https://www.youtube.com/watch?v=zt7ThwVfap0&t=32m20s

この場合:

Class()
{
    Register([this](int n){ Function(n); });
}
33
Andy

std::bind

using namespace std::placeholders;  // For _1 in the bind call

// ...

Register(std::bind(&Class::Function, this, _1));

C++ 17では、次のものを使用できます。

Register([=](auto && ...args){ return Function(args...); });

これは、特に引数リストが長い場合に適しています。もちろん、メンバー関数の引数リストはstd::functionのものと互換性がある必要があります。

3
peterchen

std::functionおよびstd::bind、異なるクラスメンバー関数を同じように扱うことができます。

#include <iostream>
#include <functional>
#include <vector>
using namespace std;
using namespace std::placeholders;

class Foo
{
public:
    void foo(const string &msg)
    {
        cout << msg << '\n';
    }
};

class Bar
{
public:
    void bar(const string &msg, const string &suffix)
    {
        cout << msg << suffix << '\n';
    }
};

int main(int argc, char **argv)
{
    Foo foo;
    Bar bar;

    vector<function<void (const string &msg)>> collection;
    collection.Push_back(bind(&Foo::foo, &foo, _1));
    collection.Push_back(bind(&Bar::bar, &bar, _1, "bar"));

    for (auto f : collection) {
        f("foo");
    }

    return 0;
}
1
Richard