In the code below, I'd like to get rid of the weird constructors taking various types of function pointers, and the parameter lists that have to be saved off (along with all the member variables that are required to hold all this), and instead use a closure to do all of that, leaving Event with a single member variable that is something like Closure closure;
. Is there a way to do this using closures in 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;
}
Prefer no boost, but if boost is best/only easy way to do this I'd like to know how.
Looks like you want
std::bind
:Alternatively you can just have the user be able to give any functor/args combo and bind it for them, like the constructor of
std::thread
:or
It seems your
Event
should just hold astd::function<double()>
in the first place: independent on using lambda or not, you want to bind the arguments to create a nullary function (as far as I can tell; if there are actual parameters to each call, you'd obviously use a corresponding signature instd::function<Signature>
.Assuming you
Event
has a memberfun
of typestd::function<double()>
and a constructor likeyou could, e.g., use
Both approaches could use
std::bind()
or lambda. I just mixed the use to get one of each. Obviously, if you use the lambda and the parameters are not constants but rather values, you'd use[=](){ ... }
to capture the closure values by value.You can use
std::bind
andstd::function
:Output
Live code
Use
std::bind
to do this. See here: http://en.cppreference.com/w/cpp/utility/functional/bindIt's in VS2012/13, and the newer GCC as well. The return value can be assigned directly to a
std::function<void()>
if you want as well.