gpt4 book ai didi

C++ 模板元编程 : Compile Time Conditional Operator on Template Type

转载 作者:太空狗 更新时间:2023-10-29 23:07:12 27 4
gpt4 key购买 nike

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

高级问题总结:

  • 我需要将变体传递给函数指针调用变体的内部值,或将变体本身传递给调用,具体取决于预期的参数类型是否为 Variant 类型。

详细信息:

当调用 Functor 时,Variants 数组用于模拟函数参数。这是我的 Functor 的重载构造函数之一的示例:

Variant operator()( Variant arg0, Variant arg1, Variant arg2 );

Variant 可以用我传递给它的任何类型的数据来构造。这一切都很好,直到我得到这段代码(这是一个特定的仿函数调用助手类,用于需要 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>( ) );
}

每个Functor存储一个函数指针,函数指针存储在一个叫做MultiFnPtr(多功能指针)的 union 中。如上所示,调用 Functor 时, union 被类型转换为适当的签名类型。传递给 Functor 的每个 Variant 都通过 GetValue 方法转换为 Variant 中保存的值。这意味着我正在将调用期间传递给 Functor 的每个 Variants 的内部数据转换为它们各自的值。要转换为的值的类型是通过将模板化的 StaticFnCall 与 MultiFnPtr 的签名相匹配推导出来的。

这是 GetValue 的实现:

template <typename TYPE>
const TYPE& VariantBase::GetValue( void ) const
{
return *reinterpret_cast<TYPE *>(data);
}

问题是我试图将一个函数签名包装在一个将 Variant 作为其参数类型之一的 Functor 中。只要在调用 Functor 时将 Variant 传递给采用 Variant 的参数,就可以了。但是,我需要将任意类型传递给采用 Variant 的参数。然后 GetValue 将用于将任意类型转换为 Variant *,这会导致该任意类型的数据在字面上被解释为 Variant,当我希望改为使用 Variant 的构造函数来创建 Variant 以传递给被调用的函数指针时在 Functor 中。

我一直在尝试想出一种直接将值传递给 StaticFnCall 的函数指针的方法,而不是在对应的模板类型为 Variant 时使用 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 ) ) );
}

最佳答案

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

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) .但我想这取决于您的其余代码的样子。

关于C++ 模板元编程 : Compile Time Conditional Operator on Template Type,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13392407/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com