13

std::placeholders::_1、std::placeholders::_2 などを入力する必要なく、メンバー関数から std::function を作成する方法

struct Foo{
  int bar(int,float,bool) {return 0;}
};
int baz(int,float,bool) {return 0;}
int main() {
  Foo object;
  std::function<int(int,float,bool)> fun1 = baz; // OK
  std::function<int(int,float,bool)> fun2 = std::bind(&Foo::bar, object); // WRONG, needs placeholders
}

この段階では引数を提供したくありません。関数 + オブジェクトをどこかに格納したいだけです。たとえば、グローバル関数とメンバー関数の両方を備えた std::vector が必要です。FastDelegate ( ) で簡単に実行できましたfastdelegate::MakeDelegate(object, &Class::function)

引数も再入力する必要があるため、ラムダを使用したくありません。古い FastDelegate の動作が必要なだけです。

4

3 に答える 3

16

次のように、すべてのメンバー関数パラメーターの型を推測する関数テンプレートを使用できます。

template<typename Obj, typename Result, typename ...Args>
auto make_delegate(const Obj &x, Result (Obj::*fun)(Args...)) -> // ...

そして、オブジェクト (またはそれへのポインター) を含む特別なデリゲート オブジェクトを返し、渡されたすべての引数を基になるオブジェクトのメンバー関数に転送します。

template<typename Obj, typename Result, typename ...Args>
struct Delegate
{
    Obj x;
    Result (Obj::*f)(Args...);

    template<typename ...Ts>
    Result operator()(Ts&&... args)
    {
        return (x.*f)(forward<Ts>(args)...);
    }
};

次の使用法構文が得られます。

function<int(int,float,bool)> fun = make_delegate(object, &Foo::bar);

完全な例は次のとおりです。

#include <functional>
#include <iostream>
#include <utility>

using namespace std;

struct Foo
{
    int bar(int x, float y, bool z)
    {
        cout << "bar: " << x << " " << y << " " << z << endl;
        return 0;
    }
};

int baz(int x, float y, bool z)
{
    cout << "baz: " << x << " " << y << " " << z << endl;
    return 0;
}

template<typename Obj, typename Result, typename ...Args>
struct Delegate
{
    Obj x;
    Result (Obj::*f)(Args...);

    template<typename ...Ts>
    Result operator()(Ts&&... args)
    {
        return (x.*f)(forward<Ts>(args)...);
    }
};

template<typename Obj, typename Result, typename ...Args>
auto make_delegate(const Obj &x, Result (Obj::*fun)(Args...))
    -> Delegate<Obj, Result, Args...>
{
    Delegate<Obj, Result, Args...> result{x, fun};
    return result;
}

int main()
{
    Foo object;
    function<int(int,float,bool)> fun[] =
    {
        baz,
        make_delegate(object, &Foo::bar) // <---- usage
    };
    for(auto &x : fun)
        x(1, 1.0, 1);
}

出力は次のとおりです。

baz: 1 1 1
bar: 1 1 1

Coliru でのライブデモ

于 2013-10-30T19:42:08.650 に答える
4

プレースホルダーを使用したくない場合は、次の方法std::bindは適していません。

ラムダを使用:

Foo object;

std::function<int(int,float,bool)> fun = [&object](int a, float b, bool c) {
        return object.bar(a,b,c);
};

object必要に応じて、値でキャプチャできます。とにかくパラメーターを入力しているので、これはプレースホルダーを使用するよりも優れているとは思わないかもしれません — 実際、この場合はもっと入力します!

于 2013-10-30T19:22:55.453 に答える