如何从成员函数创建std :: function而无需键入std :: placeholders :: _ 1,std :: placeholders :: _ 2等 - 我想“放置”所有参数,只保存对象本身。
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)
)很容易。
我不想使用lambda,因为它也需要我重新输入参数。我只想要旧的FastDelegate行为。
答案 0 :(得分:13)
您可以使用函数模板推导出所有成员函数参数类型,如下所示:
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
答案 1 :(得分:2)
如果您不想使用占位符,那么std::bind
不适合您:
使用lambda:
Foo object;
std::function<int(int,float,bool)> fun = [&object](int a, float b, bool c) {
return object.bar(a,b,c);
};
如果您愿意,可以按值捕获object
。也许您意识到这并不比使用占位符更好,因为您无论如何都要键入参数 - 事实上您在这种情况下键入 more !
答案 2 :(得分:0)
您可以使用C ++ 14中的可变参数lambda来轻松完成此任务:
template<typename F, typename C>
auto smart_bind(F f, C* c)
{
return [c, f](auto&&... args) { return (c->*f)(std::forward<decltype(args)>(args)...); };
}
// In your code:
std::function<int(int,float,bool)> fun2 = smart_bind(&Foo::bar, &object);