在下面的代码中,我想摆脱使用各种类型的函数指针的奇怪构造函数,以及必须保存的参数列表(以及保存所有这些所需的所有成员变量) ),而是使用一个闭包来完成所有这些,让Event包含一个类似于Closure closure;
的成员变量。有没有办法在C ++ 0x中使用闭包?
#include <iostream>
#include <list>
#include <functional>
#include <algorithm>
class Event
{
std::function<double(double, double)> func1;
bool func1Defined;
double double1, double2;
std::function<double(int, int, int)> func2;
bool func2Defined;
int int1, int2, int3;
public:
void setFalse()
{
func1Defined = false;
func2Defined = false;
}
Event(std::function<double(double, double)> func, double double1, double double2)
{
setFalse();
func1 = func;
func1Defined = true;
this->double1 = double1;
this->double2 = double2;
}
Event(std::function<double(int, int, int)> func, int int1, int int2, int int3)
{
setFalse();
func2 = func;
func2Defined = true;
this->int1 = int1;
this->int2 = int2;
this->int3 = int3;
}
void run()
{
double ret = 0;
if (func1Defined) ret = func1(double1, double2);
else if (func2Defined) ret = func2(int1, int2, int3);
/* do something with ret */
std::cout << ret << "\n";
}
};
double twoDoubleParam(double a, double b)
{
return a + b;
}
double threeIntParam(int a, int b, int c)
{
return (a + b) / c;
}
int main(int argc, char* argv[])
{
std::list<Event> events;
events.push_back(Event(*twoDoubleParam, 1.0, 3.5));
events.push_back(Event(*threeIntParam, 2, 4, 2));
std::for_each(events.begin(), events.end(), [&](Event event)
{
event.run();
});
int y;
std::cin >> y;
return 0;
}
不喜欢提升,但如果提升最好/只是简单的方法,我想知道如何。
答案 0 :(得分:1)
看来你的Event
应该只占一个std::function<double()>
:独立于使用lambda,你想绑定参数来创建一个nullary函数(据我所知) ;如果每个调用都有实际参数,您显然会在std::function<Signature>
中使用相应的签名。
假设您Event
有fun
类型的成员std::function<double()>
和
template <typename Fun>
Event::Event(Fun fun): fun(fun) {}
你可以,例如,使用
events.emplace_back([](){ return twoDoubleParam(1.0, 3.5); });
events.emplace_back(std::bind(&threeIntParam, 2, 4, 2));
这两种方法都可以使用std::bind()
或lambda。我只是混合使用以获得其中一个。显然,如果你使用lambda并且参数不是常量而是值,那么你可以使用[=](){ ... }
来按值捕获闭包值。
答案 1 :(得分:0)
使用std::bind
执行此操作。见这里:http://en.cppreference.com/w/cpp/utility/functional/bind
它在VS2012 / 13,以及更新的GCC。如果您愿意,也可以将返回值直接分配给std::function<void()>
。
答案 2 :(得分:0)
看起来你想要std::bind
:
std::function<void()> func;
...
Event(std::function<double(double, double)> func, double d1, double d2) {
func = std::bind(func, d1, d2);
}
// Repeat for the three ints
或者你可以让用户能够给出任何functor / args组合并为它们绑定它,比如std::thread
的构造函数:
template<typename F, typename... Args>
Event(F&& f, Args&&... args) {
func = std::bind(std::forward<F>(f), std::forward<Args>(args)...);
}
或
template<typename F, typename... Args>
Event(Args&&... args) {
static_assert(sizeof...(Args) > 1, "Event() requires more than 1 argument");
func = std::bind(std::forward<Args>(args)...);
}
答案 3 :(得分:0)
您可以使用std::bind
和std::function
:
class Event {
function<double()> func;
public:
template <typename H, typename... Args>
Event(H &&f, Args&&... args)
: func(bind(std::forward<H>(f), std::forward<Args>(args)...)) {}
void run()
{
double ret = func();
std::cout << ret << "\n";
}
};
double twoDoubleParam(double a, double b) {
return a + b;
}
double threeIntParam(int a, int b, int c) {
return (a + b) / c;
}
int main(int argc, char* argv[]) {
std::list<Event> events;
events.push_back(Event(twoDoubleParam, 1.0, 3.5));
events.push_back(Event(threeIntParam, 2, 4, 2));
std::for_each(events.begin(), events.end(), [&](Event &event)
{
event.run();
});
}
输出
4.5
3