C++从模板参数类型生成包含开关/映射的函数体
C++ generate function body containing switch/map from template argument types
我想修改现有的模板化类。该类的模板参数是(半(变量,我想使用它们来生成类似条件/开关/映射的函数体。
我的编译器不支持可变参数模板,因此(boost(预处理器当前用于生成现有类:
template <typename item0, typename item1, typename item2 ..., typename itemN>
struct myclass { /*various operations*/ };
需要一个新的函数 func,它将在运行时查询变量并返回作为模板参数之一的对象。
例:
template <typename item0, typename item1, typename item2 ...>
struct my_class {
//...various operations
//automatic generatation possible?
std::string * func()
{
string s;
while(data) {
switch (data[0])
{
case item0::id:
s += item0::get_name();
case item1::id:
s += item1::get_name();
//... for each template arguemnt typename where typename is no void
}
}
return s;
}
};
typedef my_class<a, b, c> class_one;
typedef my_class<d, e, f> class_two;
typedef my_class<a, b, c, x, y, z> class_three;
int main()
{
...
class_one test;
test.func();
...
}
我想生成func((的内容,因为项目的数量会很多,而"myclass"的类型数量会更高。
有人可以告诉我任何技术如何实现这一目标吗?
我已经依赖提升了。我的编译器相当新(但不支持可变参数模板(。我宁愿不采用任何新的依赖项或引入比必要更复杂的内容。
我以前写过这样的代码,所以我可以告诉你这是可能的。(这是用于商业的闭源工作,所以我恐怕不能向你展示代码(。你可以在 Boost.Variant 库中找到一个非常好的示例来说明如何做到这一点,特别是 http://svn.boost.org/svn/boost/trunk/boost/variant/detail/visitation_impl.hpp 。代码非常密集且C++高级,因此可能需要一两天才能彻底理解它。
快速摘要:boost::variant
类模板的工作方式类似于一个联合,带有一个 int 存储联合的哪个成员是有效的。"visitation"功能允许您为函数对象提供重载operator()
,该可以采用联合的任何可能成员,并生成一个 switch 语句,该语句访问适当的成员并调用其上的右operator()
重载。如果你已经发现这很复杂,或者你还不了解Boost.MPL,我建议你停止阅读这里,阅读Boost.Variant 文档,然后重写你的类以便能够使用它:Boost的聪明人已经为你完成了工作。它是仅标头的,因此如果您已经在使用 Boost,则没有新的依赖项。
此文件负责生成 switch 语句。简而言之,它有两种替代实现。第一个(第 72-90 行(使用递归模板visitation_impl_step
其工作原理类似于您可能已经看到的模板元编程示例的阶乘函数。非专用模板递归调用列表中的下一个模板 (typename mpl::next<Iter>::type
(。一旦所有模板都展开,生成的代码看起来有点像一系列函数 function0、function1 等,如下所示:
result_type functionN(variant vnt, visitor vr) {
if (v.which == N)
return vr(static_cast<Nth type>(vnt.value));
else
functionN-1(vnt, vr);
}
第二个实现(第 193-285 行(使用 Boost.PP 预处理器魔术库生成一个 switch 语句,就像你想要的一样,具有boost::variant
可能具有的尽可能多的情况。每个案例的主体都是对模板函数(第 120-185 行(的调用,该函数生成对第 N 个类型的访问者的调用。此实现中的大部分复杂性来自于必须担心在variant
中备份值,以便在访问者或任何涉及的构造函数抛出时保留强异常保证。
即使您决定以另一种方式执行此操作,我也建议您阅读并理解 Boost.Variant 源代码,作为学习练习。它将重新定义您对C++中可能(以及明智
将能够使用精确的模板定义生成代码。无法强制编译器在 switch 语句中生成其他情况或根据模板参数生成循环的其他迭代。
如果要对模板参数中指定的每种类型的实例执行某些操作,则必须实现递归模板函数。详情请参考本问题。
- 如何导出包含具有"std::unique_ptr"值的"std::map"属性的
- 从包含m行的文件中提取n行,必要时(惰性地)重复该文件
- 编译包含字符串的代码时遇到问题
- c++库的公共头文件中应该包含什么
- 将包含C样式数组的对象初始化为成员变量(C++)
- 既然存在危险,为什么项目要使用-I include开关
- 是否需要删除包含对象的"pair"?
- 函数何时会在c++中包含stack_Unwind_Resume调用
- 如何将包含epoch时间的十六进制字符串转换为time_t
- 使用mongocxx驱动程序时包含头文件问题
- 如何在h文件中包含.o对象文件
- 在混合代码库中将C转换为C++时出现许多包含错误
- VS2017,C++包含目录与附加包含目录,子文件夹包含失败-但为什么
- 为什么这个音频包络不能通过开关的情况?
- cmath抛出错误C2062、C2059、C2143和C2447.cmath包含在矢量文件中
- 为什么您需要C++头文件的包含保护
- 无法在UE4中包含BP类到CPP类
- 包含开关的功能在C 中不扩展内联
- 如何使用 boost::p rogram_options 解析本身包含开关的命令行参数
- C++从模板参数类型生成包含开关/映射的函数体