First let's make it a little less vomit-inducing. :)
Step 1: Make typedefs for the function-pointer types, and use them. Note that you don't need to name function parameters in these typedefs; function parameter *names* are never part of the function signature. Only the *types* matter.
Step 2: Make the Tween a little more intelligent by giving it an operator() which forwards to its tweenFunct. Actually, I'm going to rename that to remove the redundancy in naming.
Step 3: Reduce some of the &*&*ing syntax by making a reference inside the for-loop. Also pull out some of the loop invariants to remove focus from them.
That gives:
template <class T>struct Tween { typedef T (*FuncType)(float, float, std::vector<T>&); FuncType func; std::vector<T> elements; typedef void (Sprite::*propertySetter)(T); propertySetter setProp; T operator(float life, float max) { return func(life, max, elements); }};template<class T>void Particle::SetTransition(Tween<T>::FuncType tween, Tween<T>::propertySetter setProp, T* element, int length) { // add tween to list Tween* t = new Tween; t->tweenFunct = tween; t->setProp = setProp; t->elements.resize(length); for (int i=0; i<length; i++) { t->elements = element; } tweens.push_back(t); // initialize property (this->*setProp)( (*tween)(1.0f, 1.0f, t->elements) );}// And the interesting code...std::list<Tween*>::iterator iter;float life = p.GetLifeCurrent();float max = p.GetLifeMax();for (iter = p.tweens.begin(); iter != p.tweens.end(); iter++) { Tween& t = **iter; // once to get the pointer, again for a reference (p.t->setProp)(t(life, max));}
Now we can look at that with our heads cocked:
1) How are you supposed to make a list of 'Tween*', when Tween is a templated type? You need to fill in the 'something' in 'list-of-pointers-to-tween-of-something'.
2) WTF is 'p.t' supposed to be now? 't' is a variable, not a member name. I think you wanted just 't->setProp'.
3) Except that t isn't a pointer now; so it's just 't.setProp'.
4) Except that setProp is a pointer to a *member* function, so we need to invoke it upon an object. That would make it something like 'mySprite.*(t.setProp)'. Okay, so I guess 'p' in your case was the Sprite? Sigh. I think you were just getting a bad parse because of the operator precedence. But really, you shouldn't try to write things like that. PMFs are weird enough as it is. In fact, let's pull that work into the Tween member function too.
So now we have:
template <class T>struct Tween { typedef T (*FuncType)(float, float, std::vector<T>&); FuncType func; std::vector<T> elements; typedef void (Sprite::*propertySetter)(T); propertySetter setProp; void operator(Sprite& s, float life, float max) { // The problem with '(p.*(*iter)->setProp)' is that it tries to make // 'p.*(*iter)' be the bound-and-ready-to-call PMF, which is already // garbage because *iter is a Tween* rather than a PMF, and then tries to // dereference that and get a member instead of calling. // Now that we have the rest of the code factored, this goes more smoothly: (s.*setProp)(func(life, max, elements)); }};template<class T>void Particle::SetTransition(Tween<T>::FuncType tween, Tween<T>::propertySetter setProp, T* element, int length) { // add tween to list Tween* t = new Tween; t->tweenFunct = tween; t->setProp = setProp; t->elements.resize(length); for (int i=0; i<length; i++) { t->elements = element; } tweens.push_back(t); // initialize property (*t)(*this, 1.0f, 1.0f);}// And the interesting code...std::list<Tween*>::iterator iter;float life = p.GetLifeCurrent();float max = p.GetLifeMax();for (iter = p.tweens.begin(); iter != p.tweens.end(); iter++) { Tween& t = **iter; // once to get the pointer, again for a reference t(p, life, max);}
Finally, we figure out why there's this weird mismatch between 'Sprite' and 'Particle' types (which is part of what was throwing me off before). :) Oh, and why have that array-and-count interface? That's an ugly C throwback. Be generic and modern, and use an iterator pair (and add a constructor to the Tween):
template <class T>struct Tween { typedef T (*FuncType)(float, float, std::vector<T>&); FuncType func; std::vector<T> elements; typedef void (Sprite::*propertySetter)(T); propertySetter setProp; void operator(Sprite& s, float life, float max) { (s.*setProp)(func(life, max, elements)); } // Constructor! And an *initializer list*! omg! template<typename Iterator> Tween(FuncType func, propertySetter setProp, Iterator begin, Iterator end) : func(func), setProp(setProp), elements(begin, end) {}};template<class T, typename Iterator>void Particle::SetTransition(Tween<T>::FuncType tween, Tween<T>::propertySetter setProp, Iterator begin, Iterator end) { // Look how much shorter! Omg! tweens.push_back(new Tween(tween, setProp, begin, end)); // initialize property (*(tweens.back()))(*this, 1.0f, 1.0f);}