What I mean by an ‘intermediate’ functor is: a normal functor where one of the arguments can be specified at call-time. The problem is that I have an animation timeline (essentially scalar values at particular frames), and the output of this needs to be piped to and from getter/setter methods within the objects to be animated. Here is a simplified example of what I was attempting:
template < class ObjType, class Getter, class Setter, typename Scalar >
class Sy_propertyBridge : public Sy_abstractPropertyBridge
{
public:
Sy_propertyBridge( ObjType* object, Getter getter,
Setter setter )
: obj_( object ), get_( getter ),
set_( setter ) {}
virtual ~Sy_propertyBridge() {}
inline virtual float get() const
{
// Cannot handle default arguments.
Scalar tmp = ( obj_->*get_ )();
return static_cast< float >( tmp );
}
inline virtual void set( float value )
{
Scalar tmp = static_cast< Scalar >( value );
( obj_->*set_ )( tmp );
}
private:
ObjType* obj_;
Getter get_;
Setter set_;
};
The timeline only holds floats, so whatever scalar type the object uses for it’s getter/setter methods, must be cast (I have a partial specialisation for floats that does away with the cast). ObjType is the animated object type, Getter and Setter are pointers-to-methods, and Scalar is the type Getter and Setter and expected to deal with.
I thought this would be fine, but compilation failed because some of the getter/setters had other default-initialised arguments. I didn’t think this would be a problem, because they’re default! But when the compiler expected more args for the pointer-to-method than I was supplying, it failed.
I then tried using variadic template args so the default values could be manually put in, but fell at the first hurdle because I can’t store the parameter pack as a member to be repeatedly applied as args to the pointer-to-methods. I have also been looking at std::function and std::bind, I was hoping to be able to store a std::function as a member with the getter/setter method’s default args preset – and change the appropriate arg for one from the timeline just before calling. Only I can’t find a way to do that…
Does anyone have any suggestions to achieve what I am aiming for? Or is my design fundamentally flawed and there is an easier approach?
std::functionwould be the way to go. Will just usestd::function<Scalar(const ObjType*)>as your getter,std::function<void(ObjType*, Scalar)>as your setter (if theScalars are implicitly convertible to/fromfloats, I’d even usestd::function<float(ObjType const*)>andstd::function<void(ObjType*, float)>, resp.). You can initialize these eg. with lambda functions:Note that there may be more elegant ways of doing this (eg. there could be only one function that could serve both as a getter and a setter).
Taking it even further, you could
obj_member variableoparameters to the functionsThe lambdas would then have to remember the object they will operate on. So the above constructor call would become