我对'中间'仿函数的意思是:一个普通仿函数,其中一个参数可以在调用时指定。问题是我有一个动画时间轴(在特定帧上基本上是标量值),并且需要在要动画的对象内输入和输出getter / setter方法。以下是我尝试的简化示例:
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_;
};
时间轴只保存浮点数,因此无论对象使用什么标量类型的getter / setter方法,都必须进行转换(我对浮点数进行了部分特化,取消了转换)。 ObjType
是动画对象类型,Getter
和Setter
是指向方法的指针,Scalar
是Getter和Setter类型,预计会处理。
我认为这样会很好,但是编译失败了,因为一些getter / setter有其他默认初始化参数。我不认为这会是一个问题,因为它们是默认的!但是当编译器期望指针到方法的参数比我提供的更多时,它就失败了。
然后我尝试使用可变参数模板args,因此默认值可以手动输入,但是在第一个障碍下跌,因为我无法将参数包存储为成员,以重复应用为指针指向的指针方法。我一直在看std :: function和std :: bind,我希望能够将std :: function作为成员存储,并使用getter / setter方法的默认args预设 - 并从中更改相应的arg呼叫前的时间表。只有我找不到办法做到这一点......
有没有人有任何建议来实现我的目标?或者我的设计存在根本缺陷,并且有一种更简单的方法吗?
答案 0 :(得分:1)
std::function
将是最佳选择。只使用std::function<Scalar(const ObjType*)>
作为你的吸气者,std::function<void(ObjType*, Scalar)>
作为你的设定者(如果Scalar
可隐式转换为/ float
s,我甚至会使用{{1} }和std::function<float(ObjType const*)>
,resp。)。你可以初始化这些例如。 lambda函数:
std::function<void(ObjType*, float)>
请注意,可能有更优雅的方法(例如,可能只有一个函数既可以作为getter又可以作为setter)。
更进一步,你可以
Sy_propertyBridge(my_obj,
[](const MyObjType* o) -> float { return o->opacity; },
[](const MyObjType* o, float f) { o->opacity=f; })
成员变量obj_
参数然后lambdas必须记住他们将要操作的对象。所以上面的构造函数调用将成为
o
答案 1 :(得分:0)
根据我的理解,您正在尝试使用“get”和“set”方法,这些方法因您在此处传递的课程而异?如果是这样,我认为您应该尝试在“ObjType”对象上使用纯虚基类,然后在您传入的类中实现它。在C#/ Java术语中,一个接口。
基本上这个:
class IGetSetter
{
virtual float get() const = 0;
virtual void set(float) = 0;
}
class ObjType1 : public IGetSetter
{
virtual float get() const
{
// Implementation
}
virtual void set(float a)
{
// Implementation
}
}
class ObjType2 : public IGetSetter
{
virtual float get() const
{
// Implementation
}
virtual void set(float a)
{
// Implementation
}
}
然后你的班级成为:
template < typename Scalar >
class Sy_propertyBridge : public Sy_abstractPropertyBridge
{
public:
Sy_propertyBridge( IGetSetter* object)
: obj_( object ) {}
virtual ~Sy_propertyBridge() {}
inline virtual float get() const
{
Scalar tmp = obj_->get(); // Uses polymorphism to find the right method
return static_cast< float >( tmp );
}
}
inline virtual void set( float value )
{
Scalar tmp = static_cast< Scalar >( value );
obj_->set( tmp ); // Uses polymorphism to find the right method
}
private:
ObjType* obj_;
};
但实际上,可能有一种完全削减Sy_propertyBridge类的直接方法。只需存储一个指向IGetSetter
的指针数组,然后直接调用它们,如果它们符合你的要求。