首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++模板MetaProgramming:在模板类型上编译时间条件操作符

C++模板MetaProgramming:在模板类型上编译时间条件操作符
EN

Stack Overflow用户
提问于 2012-11-15 06:12:24
回答 1查看 2K关注 0票数 3

我使用模板元编程来创建变体和函子(泛型函子)数据类型。对于特定的参数类型,需要以某种方式处理参数有一个有趣的问题。理想情况下,我希望使用某种编译时条件运算符来处理方法A的给定参数,如果满足条件,则使用B,如果条件失败。

高层次问题总结

  • 我需要通过变量的内部值将变量传递给函数指针上的调用,或者根据所期望的参数类型是否为变量类型,将变量本身传递给调用。

详细信息

在调用函子时,使用变体数组来模拟函数参数。下面是我的函数的一个重载构造函数的示例:

代码语言:javascript
复制
Variant operator()( Variant arg0, Variant arg1, Variant arg2 );

这个变体可以用我传递给它的任何类型的数据来构造。在讨论这段代码之前,这一切都很好(这是一个特定的函子调用助手类,用于签名,需要3个参数):

代码语言:javascript
复制
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的实现:

代码语言:javascript
复制
template <typename TYPE>
const TYPE& VariantBase::GetValue( void ) const
{
  return *reinterpret_cast<TYPE *>(data);
}

问题是,我试图在函子中包装一个函数签名,该函式将变量作为其参数类型之一。这是很好的,只要函子被调用时,变量被传递给接受变量的参数。但是,我需要将任意类型传递给作为变量的论点。然后,GetValue将用于将任意类型转换为变量*,这将导致将任意类型的数据按字面解释为变体,当我希望使用该变量的构造函数创建变量以传递到函子内调用的函数指针时。

我一直试图找到一种直接将值传递给StaticFnCall函数指针的方法,而不是在相应的模板类型是变体时使用GetValue。我已经查过std::enable_if和sfinae,但是我很难找到一个解决方案。下面是我试图实现的伪代码的一个例子:

代码语言:javascript
复制
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>( ) );
}

编辑

因此,我发现我可以使用模板化的全局函数,并使用模板专门化来以两种方式之一处理参数。但是,这不是编译时解决方案,因为全局函数将导致分支,除非函数是内联的。

代码语言:javascript
复制
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在编译时具有重载解析,所以我认为,在不调用函数的情况下,可能会有某种方法来实现我想要的行为。使用:

代码语言:javascript
复制
#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 ) ) );
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-02-23 01:02:41

我不明白你为什么不在问题的这一部分之后停下来:

代码语言:javascript
复制
template <typename TYPE>
const TYPE& VariantBase::GetValue( void ) const
{
  return *reinterpret_cast<TYPE *>(data);
}

并为Variant添加模板专门化

代码语言:javascript
复制
template <>
const VariantBase& VariantBase::GetValue<VariantBase>( void ) const
{
  return *this;
}

做完这件事。有什么不管用的吗?在后面的问题中,似乎您一直在讨论这个解决方案,但到那时,您已经引入了无意义的ArgHandle函数、宏和助手函数,而这只是一片混乱。

就我个人而言,我会完全摆脱GetValue函数,只需提供隐式类型转换操作符,这样就可以编写fn(arg0, arg1, arg2)了。但我想这取决于您的其余代码是什么样子。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13392407

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档