使用提升预处理器以迭代方式调用可变参数模板
Using boost preprocessor to call a variadic template iteratively
假设我有一个可变参数模板:
template<typename... Args>
class Foo;
此可变参数模板递归生成另一个模板,直到它到达最后一个级别中Foo
的一个参数。现在我想有一个宏,例如Bar(...)
当我调用它时,我会得到这样的内容:
Bar(float, int, string, vector<int>)
// expands to
Macro(Foo<float, int, string, vector<int>>)
Macro(Foo<int, string, vector<int>>)
Macro(Foo<string, vector<int>>)
Macro(Foo<vector<int>>)
哪个Macro(...)
是用于在此类上执行某些操作的另一个宏。我希望能够使用Boost预处理器来减少我必须编写的代码。
请向我建议一些帮助我编写此类宏的技巧。
我不知道
这是否是解决问题的最佳方法,但这可以满足您的需求:
#include <boost/preprocessor/repetition/repeat_from_to.hpp>
#include <boost/preprocessor/seq.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>
#define CALL_MACRO(_,__,SEQ) Macro(Foo<BOOST_PP_SEQ_ENUM(SEQ)>)
#define GENERATE_MACRO_INVOCATIONS(SEQS) BOOST_PP_SEQ_FOR_EACH(CALL_MACRO,_,SEQS)
#define GENERATE_DESCENDING_SEQUENCES(_,INDEX,DATA) (BOOST_PP_SEQ_REST_N(INDEX,DATA))
#define BAR_IMPL(SEQ) GENERATE_MACRO_INVOCATIONS(BOOST_PP_REPEAT_FROM_TO(0,BOOST_PP_SEQ_SIZE(SEQ),GENERATE_DESCENDING_SEQUENCES, SEQ))
#define Bar(...) BAR_IMPL(BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))
Bar(float, int, string, vector<int>)
- 您最初有一个可变参数数据:
float, int, string, vector<int>
。 -
BOOST_PP_VARIADIC_TO_SEQ
将其转换为:(float)(int)(string)(vector<int>)
-
BOOST_PP_REPEAT_FROM_TO
调用宏GENERATE_DESCENDING_SEQUENCES
BOOST_PP_SEQ_SIZE(SEQ)
次,将序列作为数据和从 0 开始的索引。 -
BOOST_PP_SEQ_REST_N(INDEX,DATA)
从DATA
中删除INDEX
的第一个元素,并返回其余元素。这个结果放在几个括号里。 在调用 REPEAT 之后,您有一个序列序列:
((float)(int)(string)(vector))((int)(string)(vector))((string)(vector))((vector))
BOOST_PP_SEQ_FOR_EACH
对序列中的每个元素调用CALL_MACRO
。- 最后
BOOST_PP_SEQ_ENUM
获取一个序列并返回以逗号分隔的元素。
在科里鲁上进行预处理
更新:根据评论编辑答案。现在调用BOOST_EXPORT_CLASS
宏而不是我定义的macro()
函数。我没有用BOOST_EXPORT_CLASS
对此进行测试,但是,我通过访问模板扩展每个级别的Foo<...>
类型进行了模拟。我能够访问不同扩展的每个不同类型,因此我认为无论BOOST_EXPORT_CLASS
做什么都应该有效。
我认为这现在可以满足您的需求:
#define BAR(...) Foo<__VA_ARGS__>()
// Variadic definition of Foo
template <typename... Args>
struct Foo;
// Specialize Foo for the case that there is at least on template parameter
template <typename Arg, typename... Args>
struct Foo<Arg, Args...> : Foo<Args...> {
using type = Foo<Arg, Args...>;
Foo() : Foo<Args...>(){
BOOST_EXPORT_CLASS(type)
}
};
// Terminating case for Foo
template <>
struct Foo<> {
using type = Foo<>;
Foo() { BOOST_EXPORT_CLASS(type) }
};
int main() {
BAR(int, float, double);
}
为了测试这在理论上是否有效,我定义了以下宏:
#define MACRO(x) test<x>();
并用MACRO(type)
替换了BOOST_EXPORT_CLASS(type)
.函数test
如下:
template <typename T>
void test() {
std::cout << typeid(T).name() << "n";
}
运行代码打印以下内容(我添加了注释),这表明模板在宏中展开,并且应该显示为BOOST_EXPORT_CLASS
,如问题所示:
3FooIJEE // Foo<>
3FooIJdEE // Foo<double>
3FooIJfdEE // Foo<float, double>
3FooIJifdEE // Foo<int, float, double>
这是代码现场演示的现场演示。
需要注意的一点是,扩展方向与 OP 指定的方向相反,即:
Macro(Foo<>)
Macro(Foo<double>)
Macro(Foo<float, double>)
Macro(Foo<int, float, double>)
相关文章:
- 如何链接 DLL 以供 LoadLibrary() 使用(在 Windows 上的 C++ 中)并从调用 exe 导入变
- 调用参数排列不变函数 f(i++, i++)
- 访问并调用 std::function 的变体
- 我可以在输入BSTR变体上调用variantChangeType吗?
- 从C 调用Fortran子例程会产生非法参数值
- 是否有希望在std::变体上高效地调用一个公共基类方法
- 统一处理具有协变类型的函数指针(如何使用派生类型调用回调?
- 从c++调用lua函数时,如何使表和变量值保持不变
- C++构造函数调用变体
- boost变体对通用方法的简单调用
- 如何在c/c++中使函数调用之间的变量值持久化
- 斐波那契汇编x86的一个变体,不得不从c ++主方法调用它,有点丢失在几个部分
- 在调用基类构造函数之前修改构造函数参数值
- 是以前初始化的内存,保证在放置新调用后保持不变
- 注释函数的内容,但保持对函数的调用不变.编译器是否弄清楚不编译函数
- 当用gdb调试我的c++代码时,函数调用中的变量值是荒谬的
- 提升::变体 - "调用没有匹配函数"
- c++11:用向量的元素调用变差函数
- 变量值在没有scanf调用的情况下正在更改
- 调用对象作为默认实参的this