我使用模板元编程来创建变体和函子(泛型函子)数据类型。对于特定的参数类型,需要以某种方式处理参数有一个有趣的问题。理想情况下,我希望使用某种编译时条件运算符来处理方法A的给定参数,如果满足条件,则使用B,如果条件失败。
高层次问题总结
详细信息
在调用函子时,使用变体数组来模拟函数参数。下面是我的函数的一个重载构造函数的示例:
Variant operator()( Variant arg0, Variant arg1, Variant arg2 );这个变体可以用我传递给它的任何类型的数据来构造。在讨论这段代码之前,这一切都很好(这是一个特定的函子调用助手类,用于签名,需要3个参数):
template <typename R, typename T0, typename T1, typename T2>
Variant StaticFnCall3( MultiFnPtr fn, Variant& arg0, Variant& arg1, Variant& arg2 )
{
return reinterpret_cast<typename VoidToType<R>::type(*)(T0, T1, T2)>(fn.StaticFn)( arg0.GetValue<T0>( ), arg1.GetValue<T1>( ), arg2.GetValue<T2>( ) );
}每个函子存储一个函数指针,函数指针存储在一个名为MultiFnPtr (多函数指针)的联合中。在调用函子时,该联合被键入为适当的签名类型,如上文所示。传递给函子的每个变量都被转换为由GetValue方法保存在变量中的值。这意味着我将每个变量在调用过程中传递给函子的内部数据转换为各自的值。通过将模板化的StaticFnCall与MultiFnPtr的签名匹配,推导出要转换的值的类型。
下面是GetValue的实现:
template <typename TYPE>
const TYPE& VariantBase::GetValue( void ) const
{
return *reinterpret_cast<TYPE *>(data);
}问题是,我试图在函子中包装一个函数签名,该函式将变量作为其参数类型之一。这是很好的,只要函子被调用时,变量被传递给接受变量的参数。但是,我需要将任意类型传递给作为变量的论点。然后,GetValue将用于将任意类型转换为变量*,这将导致将任意类型的数据按字面解释为变体,当我希望使用该变量的构造函数创建变量以传递到函子内调用的函数指针时。
我一直试图找到一种直接将值传递给StaticFnCall函数指针的方法,而不是在相应的模板类型是变体时使用GetValue。我已经查过std::enable_if和sfinae,但是我很难找到一个解决方案。下面是我试图实现的伪代码的一个例子:
template <typename R, typename T0, typename T1, typename T2>
Variant StaticFnCall3( MultiFnPtr fn, Variant& arg0, Variant& arg1, Variant& arg2 )
{
return reinterpret_cast<typename VoidToType<R>::type(*)(T0, T1, T2)>(fn.StaticFn)( (IF_IS_VARIANT) ? arg0 : arg0.GetValue<T0>( ), (IF_IS_VARIANT) ? arg1 : arg1.GetValue<T1>( ), (IF_IS_VARIANT) ? arg2 : arg2.GetValue<T2>( ) );
}编辑
因此,我发现我可以使用模板化的全局函数,并使用模板专门化来以两种方式之一处理参数。但是,这不是编译时解决方案,因为全局函数将导致分支,除非函数是内联的。
template<typename T>
const T ArgHandle( const RefVariant& arg )
{
return arg.GetValue<T>( );
}
template<>
const Variant ArgHandle<Variant>( const RefVariant& arg )
{
return Variant( arg );
}由于函数ArgHandle在编译时具有重载解析,所以我认为,在不调用函数的情况下,可能会有某种方法来实现我想要的行为。使用:
#define ARG( NUM ) \
ArgHandle<T##NUM>( arg##NUM )
template <typename R, typename T0, typename T1, typename T2>
Variant StaticFnCall3( MultiFnPtr fn, RefVariant& arg0, RefVariant& arg1, RefVariant& arg2 )
{
return reinterpret_cast<typename VoidToType<R>::type(*)(T0, T1, T2)>(fn.StaticFn)( ARG( 0 ), ARG( 1 ), ARG( 2 ) ) );
}发布于 2013-02-23 01:02:41
我不明白你为什么不在问题的这一部分之后停下来:
template <typename TYPE>
const TYPE& VariantBase::GetValue( void ) const
{
return *reinterpret_cast<TYPE *>(data);
}并为Variant添加模板专门化
template <>
const VariantBase& VariantBase::GetValue<VariantBase>( void ) const
{
return *this;
}做完这件事。有什么不管用的吗?在后面的问题中,似乎您一直在讨论这个解决方案,但到那时,您已经引入了无意义的ArgHandle函数、宏和助手函数,而这只是一片混乱。
就我个人而言,我会完全摆脱GetValue函数,只需提供隐式类型转换操作符,这样就可以编写fn(arg0, arg1, arg2)了。但我想这取决于您的其余代码是什么样子。
https://stackoverflow.com/questions/13392407
复制相似问题