我有几个关于类方法的测试。我很难使用std :: function。 这是一个简化问题的示例代码:
#include <iostream>
#include <functional>
template<typename T>
struct Foo
{
Foo(T sum) : sum_(sum) {};
Foo<T> method_one(const Foo<T>& foo) const { Foo<T> res(sum_ + foo.sum_); return res; }
Foo<T> method_two(const Foo<T>& foo) const { Foo<T> res(sum_ + foo.sum_ + 10); return res; }
Foo<T> method_three(const Foo<T>& foo, T val) const { Foo<T> res(sum_ + foo.sum_ + val); return res;}
friend std::ostream &operator << (std::ostream & output, const Foo &foo) { output << foo.sum_; return output;}
T sum_;
};
template<typename T>
void do_the_work(const Foo<T>& a, const Foo<T>& b, const std::function<Foo<T>(const Foo<T>&)> &func)
{
// I do stuff before [...]
Foo<T> c = a.func(b);
std::cout << c << std::endl;
// I do stuff after [...]
}
int main()
{
Foo<float> a(1.0);
Foo<float> b(2.0);
// I would like to replace this
Foo<float> c = a.method_two(b);
std::cout << c; // 1 + 2 + 10
// with something like that
do_the_work(a, b, a.method_one);
do_the_work(a, b, a.method_two);
// and if possible make it more generic...
do_the_work(a, b, a.method_three, 12);
}
我尝试在main()中使用bind但没有成功:
std::function<Foo<float>(const Foo<float>&)> f = std::bind(&Foo<float>::method_one, &a);
任何其他优雅的解决方案都会很好。您可以注意到这是为了防止代码冗余并多次执行“在之前或之后执行操作”
答案 0 :(得分:2)
您缺少成员函数的隐式this
参数,您必须在std::function
签名中指定它:
template<typename T>
void do_the_work(const Foo<T>& a, const Foo<T>& b, std::function<Foo<T>(const Foo<T>&, const Foo<T>&)> func)
{
Foo<T> c = func(a, b);
...
}
请注意std::function
是如何被调用的(它不是a.foo(b)
)
并称之为:
do_the_work<float>(a, b, &Foo<float>::method_one);
do_the_work<float>(a, b, &Foo<float>::method_two);
如果你想/可以绑定将调用你的函数的对象:
template<typename T>
void do_the_work_binded(const Foo<T>& b, std::function<Foo<T>(const Foo<T>&)> func)
{
// I do stuff before [...]
Foo<T> c = func(b);
std::cout << c << std::endl;
// I do stuff after [...]
}
...
std::function<Foo<float>(const Foo<float>&)> fb = std::bind(&Foo<float>::method_one, a, std::placeholders::_1);
do_the_work_binded(b, fb);
<强> Live demo 强>
答案 1 :(得分:2)
我在std::function
的签名中跳过使用do_the_work
并在内部解决所有内容。它使得包含更多参数更容易:
template<typename T, typename Func, typename... Args>
void do_the_work(const Foo<T>& a,
const Foo<T>& b,
Func func,
Args&&... args)
{
auto f = std::bind(func, a, b, std::forward<Args>(args)...);
// I do stuff before [...]
Foo<T> c = f();
std::cout << c << std::endl;
// I do stuff after [...]
}
以后
do_the_work(a, b, &decltype(a)::method_one);
do_the_work(a, b, &decltype(a)::method_two);
// and if possible make it more generic...
do_the_work(a, b, &decltype(a)::method_three, 12);