通过接口转发构造函数参数



我需要一种通用的方式来创建任何类型的实例。此任务需要从非模板化对象执行,因此我目前正在使用如下接口:

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 的模板化对象来工作,该对象包含要构造的类型。接口中的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对象不是模板化类型,这使得很难提出参数转发解决方案。我不能简单地模板化Derived类中的New方法,因为你不能模板化虚拟方法。

如果没有一些疯狂的代码预处理,我所问的甚至可能吗?

我最终在一些朋友的帮助下收集了一个解决方案!

因此,最大的问题是要在反射中注册的所有类型都需要默认构造函数。要解决此问题,您可以使用 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 );
};

相关内容

  • 没有找到相关文章