C++ C++;试图创建一个';中级';函子
我所说的“中间”函子是指:一个普通函子,其中一个参数可以在调用时指定。问题是我有一个动画时间轴(基本上是特定帧上的标量值),它的输出需要通过管道传输到要设置动画的对象中的getter/setter方法。下面是我尝试的一个简化示例:C++ C++;试图创建一个';中级';函子,c++,callback,functor,variadic-templates,C++,Callback,Functor,Variadic Templates,我所说的“中间”函子是指:一个普通函子,其中一个参数可以在调用时指定。问题是我有一个动画时间轴(基本上是特定帧上的标量值),它的输出需要通过管道传输到要设置动画的对象中的getter/setter方法。下面是我尝试的一个简化示例: template < class ObjType, class Getter, class Setter, typename Scalar > class Sy_propertyBridge : public Sy_abstractPropertyBrid
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_;
};
template
类Sy_propertyBridge:公共Sy_abstractPropertyBridge
{
公众:
Sy_propertyBridge(对象类型*对象,Getter-Getter,
设定器(设定器)
:obj_(对象),get_(getter),
集合{(集合器){}
虚拟~Sy_propertyBridge(){}
内联虚拟浮点get()常量
{
//无法处理默认参数。
标量tmp=(obj \->*get \)();
返回静态_cast(tmp);
}
内联虚拟空集(浮点值)
{
标量tmp=静态施法<标量>(值);
(obj->*集合(tmp);
}
私人:
对象类型*对象类型;
Getter-get;
设定器设定;
};
时间轴只保存浮点数,因此无论对象用于其getter/setter方法的标量类型是什么,都必须强制转换(我对浮点数进行了部分专门化,从而消除了强制转换)ObjType
是动画对象类型,Getter
和Setter
是指向方法的指针,Scalar
是期望处理的Getter和Setter类型
我认为这很好,但编译失败了,因为一些getter/setter还有其他默认的初始化参数。我不认为这会是一个问题,因为他们是默认的!但是,当编译器预期指向方法的指针的参数比我提供的要多时,它失败了
然后,我尝试使用可变模板参数,以便可以手动输入默认值,但在第一个障碍时失败了,因为我无法将参数包存储为成员,以作为参数重复应用于方法指针。我还研究了std::function和std::bind,我希望能够使用getter/setter方法的默认参数预设将std::function存储为成员,并在调用之前从时间线中更改相应的参数。只是我找不到办法
有没有人对实现我的目标有什么建议?或者我的设计根本上有缺陷,有更简单的方法吗?据我所知,您试图使用“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:公共Sy_abstractPropertyBridge
{
公众:
Sy_propertyBridge(IGetSetter*对象)
:obj_(object){}
虚拟~Sy_propertyBridge(){}
内联虚拟浮点get()常量
{
Scalar tmp=obj->get();//使用多态性找到正确的方法
返回静态_cast(tmp);
}
}
内联虚拟空集(浮点值)
{
标量tmp=静态施法<标量>(值);
obj->set(tmp);//使用多态性找到正确的方法
}
私人:
对象类型*对象类型;
};
但实际上,有一种简单的方法可以完全取消Sy_propertyBridge类。只要存储一个指向
IGetSetter
的指针数组,然后直接调用它们(如果它们执行您想要的操作)。据我所知,您正在尝试使用“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:公共Sy_abstractPropertyBridge
{
公众:
Sy_propertyBridge(IGetSetter*对象)
:obj_(object){}
虚拟~Sy_propertyBridge(){}
内联虚拟浮点get()常量
{
Scalar tmp=obj->get();//使用多态性找到正确的方法
返回静态_cast(tmp);
}
}
内联虚拟空集(浮点值)
{
标量tmp=静态施法<标量>(值);
obj->set(tmp);//使用多态性找到正确的方法
}
私人:
对象类型*对象类型;
};
但实际上,有一种简单的方法可以完全取消Sy_propertyBridge类。只要存储一个指向IGetSetter的指针数组,然后直接调用它们(如果它们执行您想要的操作)。
std::function
就是一种方法。将只使用std::function
作为getter,std::function
作为setter(如果Scalar
s隐式转换为/从float
s,我甚至会分别使用std::function
和std::function
)。您可以使用lambda函数初始化这些函数:
Sy_propertyBridge(my_obj,
[](const MyObjType* o) -> float { return o->opacity; },
[](const MyObjType* o, float f) { o->opacity=f; })
请注意,可能有更优雅的方法来实现这一点(例如,可能只有一个函数可以同时用作getter和setter)
更进一步说,你可以
- 去掉
成员变量obj
- 将
参数去掉以o