Calling function via pointer in lambda expression - c++

I am having vector, that stores classes of type Sensor, which each have a member function refresh(). This vector is member of my class LogManager.
class Sensor
{
public:
void refresh();
}
class LogManager
{
private:
std::vector<Sensor*> sensors;
void refresh_sensors()
{
// TODO: use foreach
for (uint i=0; i<sensors.size(); i++)
{
sensors[i]->refresh();
}
for_each(sensors.begin(), sensors.end(), [sensors]( void* ) void* -> {refresh();} );
}
}
What I want to do is to change the for loop into the std::for_each() implementation. What you see above is my first try.
How can I access the member function Sensor::refresh() with the for_each() function?
Using a standard for loop like also above, I'd just use the -> operator.
Stretch goal is also to replace the std::vector<Sensor*> sensors; with a pointer: std::vector<Sensor*>* sensors; so that I do not have to work with copies. How would the implementation look in this case?

Hmm.
for_each(sensors.begin(), sensors.end(), []( Sensor * sensor ) void -> { sensor->refresh(); } );
I didn't try compiling it, so there might be a syntax problem. Things I changed:
You're not using the [sensors] section, so I emptied that.
If you're using void *, you're almost certainly doing something very un-C++-like. I changed it to the proper type.
You're not returning any value, so I changed the void * to void.
I don't actually use for_each. I personally think this code is far cleaner:
for (Sensor * sensor: sensors) {
sensor->refresh();
}
I think that's SIGNIFICANTLY easier to read. So doing it using for_each is a good practice problem, but I wouldn't have written it that way. Which also means I might have gotten the code slightly wrong.

You don't need to capture anything in the lambda in for_each. Instead, each pointer in the vector should be passed as an argument:
std::for_each(sensors.begin(), sensors.end(),
[](Sensor* s) { s->refresh();});
You don't need to (and shouldn't) make the vector a pointer, unless you want to pass it around without making copies. Since it's a private data member, that's probably not a good idea, and you can use references to do that anyway.

Related

vector of function pointers

I'm trying to code a Gameboy emulator and i would like to use a vector of function pointers to call the right function instead of doing a long switch statement.
For example if the program counter point to 0x00 (in memory), the first element of the vector is NOP so void NOP() is called;
but i can't figure how to call the functions.
Z80.h
#include <vector>
using namespace std;
class Z80;
typedef void (Z80::*function_t)();
class Z80
{
public:
vector<function_t> fmap;
...
...
};
Z80.cpp
Z80::Z80()
{
fmap = { &Z80::NOP, &Z80::LDBCnn, &Z80::LDBCmA};
}
void Z80::emulateCycle() {
opcode = memory.readByte(r.pc);
fmap[opcode](); <---ERROR
r.pc++;
}
void Z80::NOP() {
}
this is the error:
IntelliSense: expression preceding parentheses of apparent call must have (pointer-to-) function type
This expression:
fmap[opcode]
gives you a pointer to a member function. You can't just call that - it needs the class instance too. But you're actually calling it from a class method itself - so this is the instance you're looking for:
(this->*fmap[opcode])();
Note that if you want to avoid that bit of syntax and you're using C++11, you can change your fmap to instead be a vector of std::function<void()> and initialize it thusly:
fmap = { std::bind(&Z80::NOP, this), // or [this](){ this->NOP(); }
std::bind(&Z80::LDBCnn, this), // etc.
std::bind(&Z80::LDBCmA, this)};
That will let you actually do:
fmap[opcode]();
I'm not entirely sure that using function pointer in this case is particularly much better than for example a big switch statement.
However, the reason you can't call your member function is that you are not passing your object to the function.
You need this;
(this->*fmap[opcode])();
Another option is to use static/free function pointers, like this:
void (*function_t)(Z80& self);
and call it with:
fmap[opcode](this).
[Or use std::function and std::bind, which covers over the rather (intentionally, apparently) ugly syntax]

Passing function pointer with scope resolution operator arduino

I'm a newbie to arduino and programming.
I've included a library inside my own library in arduino, but first library contains a function which has a pointer function as a parameter. It is an interrupt service routine(ISR) but I need to call a function in my cpp file when interrupt is occurred. So I need to pass the pointer of that function to the first library code. It works well when I use it in .ino file, I can pass it like,
attachInterrupt(functionISR_name);
but when I use it in .cpp file, I get errors. my function is like,
void velocity::functionISR_name(){
//some code
}
but how can I pass the pointer of this function to the first library function? I tried this way but got errors,
attachInterrupt(velocity::functionISR_name);
You cannot pass a method to a function which expects a function, unless you define it static.
write it static :
static void velocity::functionISR_name()
and
attachInterrupt(&velocity::functionISR_name);
Unfortunately the static method is not bound to a specific instance any more. You should use it only together with a singleton. On Arduino you should write the class like shown below in the code snipped:
class velocity
{
static velocity *pThisSingelton;
public:
velocity()
{
pThisSingelton=this;
}
static void functionISR_name()
{
pThisSingelton->CallWhatEverMethodYouNeeded();
// Do whatever needed.
}
// … Your methods
};
velocity *velocity::pThisSingelton;
velocity YourOneAndOnlyInstanceOfThisClass;
void setup()
{
attachInterrupt(&velocity::functionISR_name);
// …other stuff…
}
This looks ugly, but in my opinion it is totally okay with Arduino as the opportunities are very limited on such a system.
Thinking again over it, I would personal go for the approach Sorin mentioned in his answer above. That would be more like that:
class velocity
{
public:
velocity()
{
}
static void functionISR_name()
{
// Do whatever needed.
}
// … Your methods
};
velocity YourOneAndOnlyInstanceOfThisClass;
void functionISR_name_delegation()
{
YourOneAndOnlyInstanceOfThisClass.functionISR_name();
}
void setup()
{
attachInterrupt(functionISR_name_delegation);
// …other stuff…
}
It would also save you some bytes for the pointer you need in the first example.
As a site note: For the future, please post the exact code (for e.g. attachInterrupt needs more parameter) and copy&paste the error messages. Usually error are exact at a place you do not suspect. This question was an exception. Normally I and other would ask for better specification.
You pass a pointer to the function but the function is a class member. Likely the call will be invalid because the this pointer will be garbage(may compile fine but will throw strange errors at runtime).
You need to define a plain vanilla function, outside of any class, and use that.
If you don't have a very complex project you can get away with having a global pointer to the class instance you should use and just delegate the call in your new function.
If you want to do thing the right way you need some mechanism to get the instance pointer I talked about above. Usually this involves either a singleton or some factory pattern.
Example:
class Foo {
void method() {
x = 5;
}
int x;
}
Having a callback on method will crash because you have an invalid pointer for this so x=5 will write 5 somewhere randomly in memory.
What you need is somehting like:
static Foo* foo_instance; // Initialized somewhere else.
void method_delegator() {
foo_instance->method();
}
Now you can pass method_delegator to the function. It will work because you now also pass foo_instance for this pointer.

Callback function pointers C++ with/without classes

I got stuck. I am trying to form a function that will eat classless function pointers and ones from objects. Here is my current code that hopefully explains more.
(It should run on a Arduino, so I cannot use big libraries.)
First off, I am using this library for the Arduino:
/* SimpleTimer - A timer library for Arduino.
* Author: mromani#ottotecnica.com
* Copyright (c) 2010 OTTOTECNICA Italy
*/
Which takes functions which it calls on a set timer interval of this type:
typedef void (*timer_callback)(void);
As far as my knowledge goes, it's a classles function, the webpage Pointers to member functions got me really far but, not far enough. Probably a terminology deficit on my side.
Now, I have made my own class which I would like in turn to use this SimpleTimer library. But if I feed the SimpleTimer my class functions, it does not like them (what I understand). But how would it be possible to make this happen without altering the SimpleTimer library.
So there is the class Robot, which has Robot::halt(). I want the robot to move forward for a set amount of time. Like so:
void Robot::forward(int speed, long time) {
reset();
timer.setTimer(time, c_func, 1);
analogWrite(l_a, speed);
analogWrite(r_a, speed);
isMoving(true);
}
void Robot::halt() {
__isMoving = false;
digitalWrite(r_a, LOW);
digitalWrite(r_b, LOW);
digitalWrite(l_b, LOW);
digitalWrite(l_a, LOW);
}
The c_func variable is a classless function at this point, but I would like to use the Robot::halt function. I have looked, read, learned but haven't succeeded yet. I just can't seem to wrap my head around this one because I am missing some angle.
I tried:
timer.setTimer(time, (this->*halt), 1);
timer.setTimer(time, Robot::*halt, 1);
timer.setTimer(time, &Robot::halt), 1);
But it would all amount to the same problem/ me just stabbing in the dark here...
EDIT
Earlier, I said not wanting to change the SimpleTimer library code. I want to comeback on this one, I guess altering it there would be the better option.
Thanks for all the current answers already, I was only allowed to flag one as a viable answer, actually everyhting I read here was extremely helpful.
To continue this, changing the SimpleTimer code. This class needs to have a reference to the object that holds my "halt" function, right? So, overloading the settimer function to something that takes my object and my function as two seperate pointers would work...? I think I am getting the hang of this but, I am not there yet with my head.
EDIT
I don't know who came with this one again but, anyone finding this thread. If found Member Function Pointers and the Fastest Possible C++ Delegates to give a very nice introduction in function pointers and member function pointers.
EDIT
Got it working, changed the SimpleTimer library to use this Delegate system:
http://www.codeproject.com/KB/cpp/FastDelegate.aspx
It integrated very nicely, and it could be nice to have a standard Delegate system like this in the Arduino library.
Code as in test (working)
typedef
typedef FastDelegate0<> FuncDelegate;
Code in robot class:
void Robot::test(){
FuncDelegate f_delegate;
f_delegate = MakeDelegate(this, &Robot::halt);
timer.setTimerDelg(1, f_delegate, 1);
}
void Robot::halt() {
Serial.println("TEST");
}
Code in SimpleTimer class:
int SimpleTimer::setTimerDelg(long d, FuncDelegate f, int n){
f();
}
Arduino prints TEST in the console.
Next step putting it in an array, don't see a lot of problems there. Thanks everyone, I can't believe the stuff I learned in two days.
What's that smell? Is that the smell of...? Success!
For the ones interested, the used Delegate system does not amount to memory capacity issues:
With FastDelegate
AVR Memory Usage
----------------
Device: atmega2560
Program: 17178 bytes (6.6% Full)
(.text + .data + .bootloader)
Data: 1292 bytes (15.8% Full)
(.data + .bss + .noinit)
Finished building: sizedummy
Without FastDelegate:
AVR Memory Usage
----------------
Device: atmega2560
Program: 17030 bytes (6.5% Full)
(.text + .data + .bootloader)
Data: 1292 bytes (15.8% Full)
(.data + .bss + .noinit)
Finished building: sizedummy
You can do this by making a functor object, that acts as a proxy between the timer code and your code.
class MyHaltStruct
{
public:
MyHaltStruct(Robot &robot)
: m_robot(robot)
{ }
void operator()()
{ robot.halt(); }
private:
Robot &m_robot;
}
// ...
timer.setTimer(time, MyHaltStruct(*this), 1);
Edit
If it can't be done via a functor object, you could global variables and functions instead, maybe in a namespace:
namespace my_robot_halter
{
Robot *robot = 0;
void halt()
{
if (robot)
robot->halt();
}
}
// ...
my_robot_halter::robot = this;
timer.setTimer(time, my_robot_halter::halt, 1);
This only works if you have one robot instance though.
Since the timer callback signature doesn't take any argument, you unfortunately need to use some global (or static) state:
Robot *global_robot_for_timer;
void robot_halt_callback()
{
global_robot_for_timer->halt();
}
you can at least wrap that lot into it's own file, but it isn't pretty. As Matthew Murdoch suggested, it might be better to edit the SimpleTimer itself. A more conventional interface would be:
typedef void (*timer_callback)(void *);
SimpleTimer::setTimer(long time, timer_callback f, void *data);
void robot_halt_callback(void *data)
{
Robot *r = (Robot *)data;
r->halt();
}
ie, when you call setTimer, you provide an argument which is passed back to the callback.
The smallest change to SimpleTimer would be something like:
SimpleTimer.h
typedef void (*timer_function)(void *);
struct timer_callback {
timer_function func;
void *arg;
};
// ... every method taking a callback should look like this:
int SimpleTimer::setTimeout(long, timer_function, void *);
SimpleTimer.cpp
// ... callbacks is now an array of structures
callbacks[i] = {0};
// ... findFirstFreeSlot
if (callbacks[i].func == 0) {
// ... SimpleTimer::setTimer can take the timer_callback structure, but
// that means it's callers have to construct it ...
int SimpleTimer::setTimeout(long d, timer_function func, void *arg) {
timer_callback cb = {func, arg};
return setTimer(d, cb, RUN_ONCE);
}
You can't pass a non-static member function there - only a static one. The signature should be like this:
static void halt()
{
//implementation
}
the reason is that each non-static member function has an implicit Robot* parameter known as this pointer which facilitates access to the current object. Since the callback signature doesn't have such Robot* parameter you can't possibly pass a member function of class Robot unless it is static.
So that in your implementation
void halt();
is in effect
static void halt( Robot* thisPointer );
and when you do
void Robot::halt() {
__isMoving = false;
}
you effectively have this:
void Robot::halt( Robot* thisPointer ) {
thisPointer->__isMoving = false;
}
and of course a halt( Robot*) function pointer can't be passed in place of void (*)(void) C callback function.
And yes, if you need access to non-static member variables of class Robot from inside the callback you'll have to somehow retrieve the pointer to class Robot instance elsewhere - for example, store it as a static member variable so that you don't rely on this pointer.
It's important to understand that function pointers and pointers to class members are different not for an arbitrary reason but the fact that instance methods have an implicit this argument (also, they have to work with inherited and virtual functions, which adds even more complexity; hence they can be 16 or more bytes in size). In other words, a function pointer to a class member is only meaningful together with an instance of the class.
As the currently-top answer says, your best bet is to go with functors. While the setTimer function might only accept function pointers, it is possible to write a template function to wrap the call and accept both. For even more fine-grained processing, you can write a template metaprogram (Boost.TypeTraits has is_pointer, is_function and even is_member_function_pointer) to handle the different cases.
How you make the functors is a different story. You can opt for writing them by hand (which means implementing a class with operator() for each one of them), but depending on your needs that might be tedious. A couple of options:
std::bind: you can use it to create a functor whose first parameter will be bound to the value you specify - in the case of member functions, it will be the instance.
Depending on your compiler, you might not have access to std::bind - in this case I suggest boost::bind. It is a header-only library and provides the same functionality.
You can use another delegate implementation. I don't have experience with this one, but claims to be faster than other implementations (including std::function).
The mentioned libraries are header-only, so they probably don't count as "big libraries".

Most effective method of executing functions an in unknown order

Let's say I have a large, between 50 and 200, pool of individual functions whose job it is to operate on a single object and modify it. The pool of functions is selectively put into a single array and arranged in an arbitrary order.
The functions themselves take no arguments outside of the values present within the object it is modifying, and in this way the object's behavior is determined only by which functions are executed and in what order.
A way I have tentatively used so far is this, which might explain better what my goal is:
class Behavior{
public:
virtual void act(Object * obj) = 0;
};
class SpecificBehavior : public Behavior{
// many classes like this exist
public:
void act(Object * obj){ /* do something specific with obj*/ };
};
class Object{
public:
std::list<Behavior*> behavior;
void behave(){
std::list<Behavior*>::iterator iter = behavior.front();
while(iter != behavior.end()){
iter->act(this);
++iter;
};
};
};
My Question is, what is the most efficient way in C++ of organizing such a pool of functions, in terms of performance and maintainability. This is for some A.I research I am doing, and this methodology is what most closely matches what I am trying to achieve.
edits: The array itself can be changed at any time by any other part of the code not listed here, but it's guaranteed to never change during the call to behave(). The array it is stored in needs to be able to change and expand to any size
If the behaviour functions have no state and only take one Object argument, then I'd go with a container of function objects:
#include <functional>
#include <vector>
typedef std::function<void(Object &)> BehaveFun;
typedef std::vector<BehaveFun> BehaviourCollection;
class Object {
BehaviourCollection b;
void behave() {
for (auto it = b.cbegin(); it != b.cend(); ++it) *it(*this);
}
};
Now you just need to load all your functions into the collection.
if the main thing you will be doing with this collection is iterating over it, you'll probably want to use a vector as dereferencing and incrementing your iterators will equate to simple pointer arithmetic.
If you want to use all your cores, and your operations do not share any state, you might want to have a look at a library like Intel's TBB (see the parallel_for example)
I'd keep it exactly as you have it.
Perofmance should be OK (there may be an extra indirection due to the vtable look up but that shouldn't matter.)
My reasons for keeping it as is are:
You might be able to lift common sub-behaviour into an intermediate class between Behaviour and your implementation classes. This is not as easy using function pointers.
struct AlsoWaveArmsBase : public Behaviour
{
void act( Object * obj )
{
start_waving_arms(obj); // Concrete call
do_other_action(obj); // Abstract call
end_waving_arms(obj); // Concrete call
}
void start_waving_arms(Object*obj);
void end_waving_arms(Object*obj);
virtual void do_other_actions(Object * obj)=0;
};
struct WaveAndWalk : public AlsoWaveArmsBase
{
void do_other_actions(Object * obj) { walk(obj); }
};
struct WaveAndDance : pubic AlsoWaveArmsBase
{
void do_other_actions(Object * obj) { walk(obj); }
}
You might want to use state in your behaviour
struct Count : public Behavior
{
Behaviour() : i(0) {}
int i;
void act(Object * obj)
{
count(obj,i);
++i;
}
}
You might want to add helper functions e.g. you might want to add a can_act like this:
void Object::behave(){
std::list<Behavior*>::iterator iter = behavior.front();
while(iter != behavior.end()){
if( iter->can_act(this) ){
iter->act(this);
}
++iter;
};
};
IMO, these flexibilities outweigh the benefits of moving to a pure function approach.
For maintainability, your current approach is the best (virtual functions). You might get a tiny little gain from using free function pointers, but I doubt it's measurable, and even if so, I don't think it is worth the trouble. The current OO approach is fast enough and maintainable. The little gain I'm talking about comes from the fact that you are dereferencing a pointer to an object and then (behind the scenes) dereferencing a pointer to a function (which happening as the implementation of calling a virtual function).
I wouldn't use std::function, because it's not very performant (though that might differ between implementations). See this and this. Function pointers are as fast as it gets when you need this kind of dynamism at runtime.
If you need to improve the performance, I suggest to look into improving the algorithm, not this implementation.

Accomplish this task in C++; Migration from AS3.0

I've got way too much information to work with, so for now I'll consider this question answered until I can sort it all out and decide on the final implementation! Thanks a ton gf and Simon Buchan. I wish I could accept both of your answers, since they're both definite possibilities!
Additional / Revised Conceptual Information as suggested:
What I am aiming to do;
I am making a game. In this game every object used is an instance of the DOBJ class. The TUR class extends the DOBJ class. The SHO class extends the TUR class.
Each TUR class has an array of SHO's stored in it's SHOARR array. Each SHO instance needs to be given a set of instructions.
I know for a fact I could make 1000's of different SHO classes that have their instructions set during construction.
However, considering I will have so many different acting SHO instances, I was interested in another way to pass a set of instructions. Through the contruction of the SHO would be the ideal.
The instructions I am attempting to pass to each SHO are simple if statements;
if(frame > 64) { rotation += 4; };
if(state == 0 && frame < 32) { xs = 12; ys = 12; state = 1; };
Original question
Migration from ActionScript3.0 to C++ is proving to be a trial indeed. Thanks to those who have answered my questions thus far and also to those who opened stackoverflow in the first place. Onto the question... (TL;DR near the bottom to get straight to the question)
I'm attempting to apply the same logic that I could apply in AS3.0 to my project in C++ and it's just not going very well.
In AS3.0 I was used to slapping any and every datatype into an Array. It made things pretty simple. Now that I've run into C++ dev, I realized that I can't exactly do that anymore.
So now I'm stuck with this problem of rewriting a little AI system in a new language, where the driving point of the system isn't even compatible!
Here's an example of a piece of the code I was writing in AS3.0;
AI[NUM][1]( OBJ, AI[NUM][2], AI[NUM][3] );
AI being an array, NUM being an integer, OBJ being an instance of a class.
This line obviously called the function in the second element of the first array in the main array with the arguments being a class in which to perform the function on, whatever was in the third element of the first array of the main array, and likewise the fourth element.
In this case;
AI[NUM][1] would be a function
AI[NUM][2] would be a variable
AI[NUM][3] would be a number
Generally, my AI was run on calling a function to change or compare the variable with a number.
An example would be;
CompareST( someObject, "x", 500 );
and return true if someObject's x variable was smaller than (ST) 500.
The AI array itself was just filled with arrays of calls similar to this.
Quite new to C++ I had no idea how to go about this, so I did a bit of searching and reading of many different websites and came to the conclusion that I should look into function pointers.
However, after reading a bit into them, I've come to the conclusion that it won't help me realize my goal. While it did help me call functions like I wanted to call them, it doesn't help me stack different datatypes into one large array of arrays.
TL;DR
EDIT++:
What I need for each object is a set of instructions to be checked every frame. However, for each instance of the class, the instructions have to be different.
I plan on having a LOT of different instances, so making a class for each one is unreasonable.
Thus, I needed a way to pass a set of instructions to each one through it's constructor and read + execute them at any time their think() function is called.
My ultimate goal (aside from finding out about a better way to go about this) would be to be able to have an array of function calls, like;
A[n][0]( O, A[n][1], A[n][2] );
Where;
O is the instance the function is altering
A[n][0] is a function (Equality or Comparison)
A[n][1] is the variable, eg; "x", O["x"] (or a pointer to that variable in the case of C++)
A[n][2] is the value to alter the variable by, or compare it to.
And I'm not sure how I would rewrite this into C++, or alter it to work in another way.
Aftermath / Additional Information
What I'm actually aiming to do is be able to give an object a set of instructions at the time of it's creation, through the constructor. For example upon creation give an object instructions to wait 64 frames, and then rotate in the opposite direction, would have been something like this;
t.AI = [ [ 1, AIF.CompareET, "STATE", 0, AIF.CompareGT, "FRAME", 64, 0, AIF.EqualityAT, "baseRotation", 180, AIF.EqualityET, "STATE", 1 ] ];
In pseudocode;
(The 1 in the array denotes how to read the rest of the array, in this case everything before the odd 0 [ The one that comes after 64 ] is a comparison. If any of those fail, anything after the 0 will not be looked at )
Compare STATE is equal to (ET) 0, if true
Compare FRAME is greather than (GT) 64, if true
Add 180 to (AT) baseRotation, Set STATE equal to 1
Sorry that this turned out really long. I hope it's understandable, and I'm not asking something stupidly difficult to explain.
You can store functions using function pointers or functors. Variant types though are not natively supported by C++, you have to use custom solutions there.
One possibility would be to use Boost.Any (or better, Boost.Variant if you only use a fixed set of types):
typedef void (*Function)(Object*, const std::string&, boost::any&);
std::vector<Function> functions;
Given some function:
void f(Object* obj, const std::string& name, boost::any& value) {
// ...
}
you could store and call it similar to your example:
functions.push_back(&f);
functions[0](obj, "x", boost::any(500));
To utilize a declarative syntax, there are three options that come to my mind:
you use a similar approach and have central "interpreter" function, e.g. based on a switch (don't forget to switch to integers or pointers-to-members instead of strings if you need performance)
you invent your own language and generate C++ code from description files
you compose function objects in a declarative way
To do composition, you could use Boost.Bind or something like custom objects that represent operations:
struct Operation {
virtual ~Operation() {}
virtual bool operator()(Object&) = 0;
};
template<class T>
struct GreaterThen : Operation {
typedef T Object::*Member;
Member member;
const T value;
CompareGT(Member member, const T& value) : member(member), value(value) {}
bool operator()(Object& obj) { return (obj.*member > value); }
};
template<class T>
struct SetTo : Operation {
typedef T Object::*member;
Member member;
const T value;
SetTo(Member member, const T& value) : member(member), value(value) {}
bool operator()(Object& obj) { obj.*member = value; return true; }
};
Now we can build operation lists:
typedef std::vector<Operation*> OpList;
OpList operation;
operations.push_back(new GreaterThen<int>(&Object::Frame, 64));
operations.push_back(new SetTo<int>(&Object::State, 1));
We can use helper functions to avoid having to specify the template types:
template<class T>
Operation* opGreaterThen(T Object::*mem, const T& val) {
return new GreaterThen<T>(mem, val);
}
Assuming a similar helper for SetTo and using Boost.Assign the above becomes:
OpList operations = boost::assign::list_of
(opGreaterThen(&Object::Frame, 64))
(opSetTo (&Object::State, 1));
Executing the operations becomes the following then:
OpList::iterator it = operation.begin();
for( ; it != operations.end(); ++it) {
Operation& op = *it; // just for readability
if(!op(someObject)) break; // stop if operation returns false
}
Wow.
Reading through that slowly suggests what you're trying to end up with is an array of function calls and you can choose a different function with the same parameters (but different implementation) for different actions and choose the correct one for the correct case.
If that is the case, you're looking for function pointers. Try this tutorial.
You should be able to use a function pointer with an argument set and point it to the correct function based on your needs. You won't need an array of function pointers for this either - any function that matches the definition should do. From the tutorial, declare a function pointer like this:
int (TMyClass::*functptr)(classname, int, int) = NULL; // C++
Then assign it later:
this.functptr = &TMyClass::doitthisway;
While it is possible (although a pain) to have an array of arbitrary types, you pretty much never need it, since you have to know something about what is where to do anything interesting with it: for example, your 'TL;DR' example seems to look something like:
struct AIRule {
// Can only handle comparing ints, see later for more general solution.
typedef bool compare_type(AIObject*, AIObject::*int, int);
compare_type* compare;
AIObject* object;
AIObject::int* member;
int comparand;
};
So now you can do something like:
bool ai_equal(AIObject* object, AIObject::int* member, int comparand) {
return object->*member == comparand;
}
...
ai[n].compare = &ai_equal;
ai[n].object = some_object;
ai[n].member = &AIObject::some_member;
ai[n].comparand = 50;
...
if (ai[n].compare(ai[n].object, ai[n].member, ai[n].comparand)) {
...
}
This just moves the any type problem from the rules array to member though. C++ needs to know at least how many bytes a member is, and a string (for example) can be much bigger than an int. You can get around this by using pointers: which essentially is C++'s version of any, but you then need to delete it yourself (or you will leak memory!), at which point the interface method below becomes simpler.
If I was doing what you seem to want, I would use inheritance:
struct Sprite {
int frame;
double rotation;
Sprite() {
frame = 0;
rotation = 0.0;
}
virtual ~Sprite() {}
virtual void think() {
++frame;
}
virtual void draw() {
...
}
};
struct RotatingSprite : public Sprite {
int state;
MyShape() {
state = 0;
}
void think() {
Sprite::think();
if (state == 0 && frame > 64) {
state = 1;
rotation += 180.0;
}
}
};
Or a function pointer:
struct Sprite {
int frame;
double rotation;
void (*think)(Sprite*);
Sprite() {
frame = 0;
rotation = 0.0;
}
};
void rotate_think(Sprite* sprite) {
if (sprite->state == 0 && sprite->frame > 64) {
sprite->state = 1;
sprite->rotation += 180.0;
}
}
...
sprite->think = &rotate_think;
If you really need to do it dynamically I would recommend using the ++ part of C++. For the predicates (a predicate is just something that returns a boolean, like isLowerCase()) create an AIPredicate interface, and the actions an AIAction interface:
struct AIPredicate {
// "When you delete an AIPredicate, delete the full type, not just this interface."
virtual ~AIPredicate() {}
// "You can treat this as a function (operator()) but I'm not providing an implementation here ( = 0)"
virtual bool operator()(AIObject* object) = 0;
};
struct AIAction {
virtual ~AIAction() {}
virtual void operator()(AIObject* object) = 0;
};
struct AIRule {
// std::auto_ptr (or std::unique_ptr if you can use C++0x) will delete predicate for you.
// Add "#include <memory>" to your includes if it complains (most std headers will include it already)
std::auto_ptr<AIPredicate> predicate;
std::auto_ptr<AIAction> action;
};
Now you can make types like:
struct AIFrame : public AIPredicate {
// Implement the operator() member AICondition promises.
bool operator()(AIObject* object) {
return object->foo < 100;
}
};
...
// Use .reset() instead of = if you use std::unique_ptr.
ai[n].predicate = new AIFooIsLow();
If you want to have a very general predicate type, you can use the very powerful (and complicated) templates feature:
// The naming convention I'm using here is 'T'TitleCase for template parameters, TitleCase for types,
// lower_case for arguments and variables and '_'lower_case for members.
template<typename TMemberType, AIObject::TMemberType* TMember>
struct AIMemberEquals : public AIPredicate {
// Constructor: Initializes a new instance after it is created.
AIMemberEquals(TMemberType comparand) {
// Save comparand argument so we can use it in operator().
_comparand = comparand;
}
bool operator()(AIObject* object) {
return object->*TMember == comparand;
}
// Stores the value to compare.
TMemberType _comparand;
};
Unfortunately, creating templates looks a bit crazy:
ai[n].predicate = new AIMemberEquals<int, &AIObject::some_member>(100);
Read it as "create a new instance of (the type that AIMemberEquals applied to int and (the some_member member of AIObject) creates), with the argument 100".
When you have multiple predicates memory management becomes a bit more difficult without C++0x's unique_ptr or shared_ptr, types that will delete the object for you, since std::auto_ptr doesn't work in containers:
#include <vector>
struct AIData {
// vector is fairly close to AS3's Array type, it is a good default for
// arrays of changing or unknown size.
std::vector<AIPredicate*> predicates;
// Destructor: will be run before the memory for this object is freed.
~AIData() {
for (int i = 0; i != predicates.size(); ++i) {
delete predicates[i];
}
}
};
...
ai[n].predicates.push_back(new AIFooIsLow());
...
for (int i = 0; i != ai[n].predicates.size(); ++i) {
(*ai[n].predicates[i])(ai[n].object);
}
In C++0x:
struct AIData {
// unique_ptr will delete it for you, so no ~AIData() needed.
std::vector<unique_ptr<AIPredicate>> predicates;
};
Your final example could in C++ look something like:
std::auto_ptr<Shape> shape(new Shape());
...
std::auto_ptr<AIRule> rule(new AIRule());
rule->predicates.push(new AIMemberEquals<int, &Shape::state>(0));
rule->predicates.push(new AIMemberGreater<int, &Shape::frame>(64));
rule->actions.push(new AIAddMember<double, &Shape::rotation>(180.0));
rule->actions.push(new AISetMember<int, &Shape::state>(1));
shape->ai.push(rule); // .push(std::move(rule)); if you are using unique_ptr
Certainly not as pretty, but it works and is fairly flexible.