我需要一种通用的方法来创建任何类型的实例。此任务需要从非模板化对象执行,因此我当前正在使用如下界面:
class Interface
{
public:
virtual void PlacementCopy( void *data, const void *src ) const = 0;
virtual void PlacementNew( void *data ) const = 0;
virtual void PlacementDelete( void *data ) const = 0;
virtual void Delete( void *data) const = 0;
virtual void Copy( void *dest, const void *src ) const = 0;
virtual void NewCopy( void **dest, const void *src ) const = 0;
virtual void *New( ) const = 0;
};
这是自定义反射系统的一部分,所以它的使用方式如下:
int *p = META( int )->Interface->New( );
*p = 10;
这可以通过创建一个派生自Interface
的模板化对象来实现,该对象包含要构造的类型。 Interface中的New
运算符执行类型的默认构造:
template <typename T>
class Derived : public Interface
{
virtual void *New( void ) const override
{
return new T( );
}
};
问题: 以这种方式构造的所有类型都必须提供默认构造函数。我想以某种方式允许将任意参数传递给相关类型的构造函数。
我不知何故需要能够做到:
MetaInfo *meta = META( SomeType );
SomeType *object = meta->New( arg1, arg2 );
在实施中可能看起来像这样:
template <typename T>
Derived : public Interface
{
template <typename ... Args>
virtual void *New( Args&& ... args ) const override
{
new T( std::forward<Args>( args ) ... );
}
};
MetaInfo
对象不是模板化类型,因此很难提出参数转发解决方案。我不能简单地对New
类中的Derived
方法进行模板化,因为您无法模拟虚拟方法。
如果没有一些疯狂的代码预处理,我甚至可以问这个问题吗?
答案 0 :(得分:0)
我最终在一些朋友的帮助下聚集了一个解决方案!
所以最大的问题是在反射中注册的所有类型都需要默认构造函数。为了解决这个问题,您可以使用SNIFAE来检查是否存在默认构造函数。
struct HasDefaultCtor
{
template <typename U>
static int32 SFINAE( decltype( U( ) ) * );
template <typename U>
static int8 SFINAE( ... );
static const bool value = sizeof( SFINAE<T>( NULL ) ) == sizeof( int32 );
};
除此之外,所有非默认构造函数都必须在反射系统中手动注册,或者使用预构建步骤工具生成。其他SNIFAE检查可用于类型检查,并确保已注册的构造函数实际匹配类中的实际构造函数。为了实际调用New
运算符,需要进行一些运行时解析,以便找出与New
调用匹配所需的构造函数。
我希望这是有道理的,并且最终会对将来的人有用。
我还对复制构造函数进行了SNIFAE检查:
template <typename T>
struct HasCopyCtor
{
static T MakeT( void );
template <typename U>
static int32 SFINAE( decltype( U( MakeT( ) ) ) * );
template <typename U>
static int8 SFINAE( ... );
static const bool value = sizeof( SFINAE<T>( NULL ) ) == sizeof( int32 );
};