So, I did a reasonable amount of googling first, but all of the solutions seem unreasonably complex. So, I thought I'd ask here to see if this task really requires the kind of approach I've been encountering...
So, say I have an Event
class. I would like it to have a time
variable, and a functionToExecuteAtTime
function pointer / variable / magic piece of code that lets me pass any old function to this class.
Also I would like the events held in a priority queue that arranges the events in order of time and executes the functions they are "carrying". But forget about this for now
Something like this...
class Agent
{
public:
int id;
float cash;
Agent::Agent
{
cash = 100;
}
}
class uberSystem
{
public:
float assets;
int supplyOfDeadlyPoison;
float poisonCost;
std::vector<Agent> agents;
uberSystem::uberSystem
{
assets = 100000;
supplyOfDeadlyPoison = 100000;
poisonCost = 8;
for(int i = 0; i < 100; i++)
{
Agent newAgent;
newAgent.id = i;
agents.push_back(newAgent)
}
}
};
class Event
{
public:
int time;
SOMETHING_THAT_LETS_ME_HOLD_FUNCTIONS myFunction;
Event::Event(int t, SOMETHING_THAT_LETS_ME_HOLD_FUNCTIONS func)
{
time = t;
myFunction = func;
}
}
int uselessFunction()
{
return 42;
}
void buyPoisonAndKillAgent(Agent &myAgent, uberSystem &mySystem)//obviously not good...
{
myAgent.cash -= mySystem.poisonCost;
mySystem.assets += mySystem.poisonCost;
mySystem.agents.erase(mySystem.agents.begin()+myAgent.id);
mySystem.supplyOfDeadlyPoison -= 1;
}
int main()
{
uberSystem newSystem;
// Event newEvent(100, uselessFunction());//make a new event
Event newEvent(100, buyPoisonAndKillAgent(newSystem.agents[5], newSystem));
newEvent.myFunction;//run the bloody function
return 0;
}
Okay, so that looks like extremely wishful thinking now that I type it. So, how can I achieve this? Is function pointers the way to go? Or is there some better way that I have somehow managed to not find yet?
Oh, and apparently I do have std::function
available after all... I was not in the stone age all along!
Thanks!
Why not do this
then
This seems simpler and you have the luxury of adding whatever data is required for the event.
For a list you use
Event
pointers e.g.Event *e = new MyEvent(100)
The simplest way to hold a generic function or closure is to use
std::function
; in the absence of C++11boost::function
is a good placeholder for it.This yields:
Note that the signature of the function need be precised:
void()
is a function taking no argument and returning nothing.Also, note that you can arbitrary predicates, functor classes or lambdas, as long as one of the
operator()
matches the expected signature.You can have a Base class Event (as proposed by @EdHeal) and then have a templated subclass storing your function pointer:
With the helper function
make_event
it is easy to call and deduces the type automatically:Of course, if there is access to C++11 (or TR1, or boost) there is no need for all this at all (as other answers describe)