- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用模板元编程来创建 Variant 和 Functor(通用仿函数)数据类型。我有一个有趣的问题,需要针对特定参数类型以某种方式处理参数。理想情况下,我想使用某种编译时条件运算符来处理给定的参数,如果满足条件,则使用方法 A,如果条件失败,则使用方法 B。
高级问题总结:
详细信息:
当调用 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/
我正在尝试打印 timeval 类型的值。实际上我可以打印它,但我收到以下警告: 该行有多个标记 格式“%ld”需要“long int”类型,但参数 2 的类型为“struct timeval” 程序
我正在编写自己的 unix 终端,但在执行命令时遇到问题: 首先,我获取用户输入并将其存储到缓冲区中,然后我将单词分开并将它们存储到我的 argv[] 数组中。IE命令是“firefox”以启动存储在
我是 CUDA 的新手。我有一个关于一个简单程序的问题,希望有人能注意到我的错误。 __global__ void ADD(float* A, float* B, float* C) { con
我有一个关于 C 语言 CGI 编程的一般性问题。 我使用嵌入式 Web 服务器来处理 Web 界面。为此,我在服务器中存储了一个 HTML 文件。在此 HTML 文件中包含 JavaScript 和
**摘要:**在代码的世界中,是存在很多艺术般的写法,这可能也是部分程序员追求编程这项事业的内在动力。 本文分享自华为云社区《【云驻共创】用4种代码中的艺术试图唤回你对编程的兴趣》,作者: break
我有一个函数,它的任务是在父对象中创建一个变量。我想要的是让函数在调用它的级别创建变量。 createVariable testFunc() [1] "test" > testFunc2() [1]
以下代码用于将多个连续的空格替换为1个空格。虽然我设法做到了,但我对花括号的使用感到困惑。 这个实际上运行良好: #include #include int main() { int ch, la
我正在尝试将文件写入磁盘,然后自动重新编译。不幸的是,某事似乎不起作用,我收到一条我还不明白的错误消息(我是 C 初学者 :-)。如果我手动编译生成的 hello.c,一切正常吗?! #include
如何将指针值传递给结构数组; 例如,在 txt 上我有这个: John Doe;xxxx@hotmail.com;214425532; 我的代码: typedef struct Person{
我尝试编写一些代码来检索 objectID,结果是 2B-06-01-04-01-82-31-01-03-01-01 . 这个值不正确吗? // Send a SysObjectId SNMP req
您好,提前感谢您的帮助, (请注意评论部分以获得更多见解:即,以下示例中的成本列已添加到此问题中;西蒙提供了一个很好的答案,但成本列本身并未出现在他的数据响应中,尽管他提供的功能与成本列一起使用) 我
我想知道是否有人能够提出一些解决非线性优化问题的软件包的方法,而非线性优化问题可以为优化解决方案提供整数变量?问题是使具有相等约束的函数最小化,该函数受某些上下边界约束的约束。 我已经在R中使用了'n
我是 R 编程的初学者,正在尝试向具有 50 列的矩阵添加一个额外的列。这个新列将是该行中前 10 个值的平均值。 randomMatrix <- generateMatrix(1,5000,100,
我在《K&R II C 编程 ANSI C》一书中读到,“>>”和“0; nwords--) sum += *buf++; sum = (sum >>
当下拉列表的选择发生变化时,我想: 1) 通过 div 在整个网站上显示一些 GUI 阻止覆盖 2)然后处理一些代码 3) 然后隐藏叠加层。 问题是,当我在事件监听器函数中编写此逻辑时,将执行 onC
我正在使用 Clojure 和 RESTEasy 设计 JAX-RS REST 服务器. 据我了解,用 Lisp 系列语言编写的应用程序比用“传统”命令式语言编写的应用程序更多地构建为“特定于领域的语
我目前正在研究一种替代出勤监控系统作为一项举措。目前,我设计的用户表单如下所示: Time Stamp Userform 它的工作原理如下: 员工将选择他/她将使用的时间戳类型:开始时间、超时、第一次
我是一名学生,试图自学编程,从在线资源和像您这样的人那里获得帮助。我在网上找到了一个练习来创建一个小程序来执行此操作: 编写一个程序,读取数字 a 和 b(长整型)并列出 a 和 b 之间有多少个数字
我正在尝试编写一个 shell 程序,给定一个参数,打印程序的名称和参数中的每个奇数词(即,不是偶数词)。但是,我没有得到预期的结果。在跟踪我的程序时,我注意到,尽管奇数词(例如,第 5 个词,5 %
只是想知道是否有任何 Java API 可以让您控制台式机/笔记本电脑外壳上的 LED? 或者,如果不可能,是否有可能? 最佳答案 如果你说的是前面的 LED 指示电源状态和 HDD 繁忙状态,恐怕没
我是一名优秀的程序员,十分优秀!