Trick : filling array values using macros (code generation)(技巧:使用宏填充数组值(代码生成))
问题描述
C++ 模板只是变相的宏吗?
我正在阅读上面的主题,突然想到一个想法:为什么不尝试编写一些可以在我们的实际代码中使用的棘手宏(不仅仅是在现实生活中无用的谜题)?
I was reading the above topic, and suddenly this idea came to my mind: why not try writing some tricky macros which can be used in our real code, (not just only as puzzles which are useless in real life)?
所以首先想到的是:用宏填充数组值:
So the first thing came to mind is : filling array values with macros:
int f(int &i) { return ++i; }
#define e100 r5(m20)
#define m20 m5,m5,m5,m5
#define m5 r5(e1)
#define e1 f(i) //avoiding ++i right here, to avoid UB!
#define r5(e) e,e,e,e,e
int main() {
int i=0; //this is used in the macro e1
int a[] = {e100}; //filling array values with macros!
int n = sizeof(a)/sizeof(int);
cout << "count = " << n << endl;
for(int i = 0 ; i < n ; i++ )
cout << a[i] << endl;
return 0;
}
输出:
count = 100
1
2
3
4
.
.
.
100
在线演示:http://www.ideone.com/nUYrq
我们能否在紧凑性或通用性(可能两者兼而有之)方面进一步改进此解决方案?我们可以去掉宏中需要的变量i吗?还是有其他改进?
Can we further improve this solution in terms of compactness or genericity (possibly both)? Can we get rid of the variable i which we need in the macro? Or any other improvement?
我也想知道这是否是 C++ 和 C 中的有效代码(当然忽略打印部分)?
I would also like to know if that is valid code both in C++ and C (of course ignoring printing part)?
我意识到对 f() 的调用顺序似乎仍然未指定.不过我不确定,因为我认为数组初始化中的逗号 not 可能与逗号运算符相同(通常).但如果是,我们可以避免它吗?标准的哪一部分说它未指定?
I realized that the order of calls to f() seems still unspecified. I'm not sure though, as I think comma in array initialization is not probably same as comma operator (in general). But if it is, can we avoid it and what part of the Standard says its unspecified?
推荐答案
如果你想深入研究预处理器编程,我只能推荐 Boost.Preprocessor 库作为构建块,您将避免从头开始重写.
If you wish to delve into Preprocessor programming, I can only recommend the Boost.Preprocessor library as a building block, you'll avoid having to rewrite things from scratch.
例如,为了创建您的表格,我会使用 (ideone):
For example, in order to create your table, I would have used (ideone):
#include <iostream>
#include <boost/preprocessor/repetition/enum.hpp>
#define ORDER(z, n, text) n
int main() {
int const a[] = { BOOST_PP_ENUM(100, ORDER, ~) };
std::size_t const n = sizeof(a)/sizeof(int);
std::cout << "count = " << n << "
";
for(std::size_t i = 0 ; i != n ; ++i )
std::cout << a[i] << "
";
return 0;
}
把所有的琐事留给 Boost :)
And leave all the cruft to Boost :)
注意:这里枚举的是 0 到 99,而不是 1 到 100,还有其他操作可用于执行算术运算;)
这是如何工作的?
首先,我只能推荐 BOOST_PP_ENUM
BOOST_PP_ENUM 是一个带有 3 个参数的宏:(n, MACRO, data)
BOOST_PP_ENUM is a macro which takes 3 arguments: (n, MACRO, data)
n:一个整数MACRO:一个接受 3 个参数的宏:(z, i, data)data:为方便起见,传递给macro的一些数据
n: an integerMACRO: a macro accepting 3 arguments:(z, i, data)data: some data, of your convenience, to be passed tomacro
然后它将被 n 次连续调用 MACRO 替换,用逗号分隔:
It will then be replaced by n successive invocations of MACRO separated by commas:
MACRO(z, 0, data), MACRO(z, 1, data), ... , MACRO(z, n-1, data)
你可以用你的MACRO做任何你想做的事.
It is up to you to do whatever you wish with your MACRO.
z参数我恐怕没用过,它是在内部使用的,理论上你可以用它来加快进程.
I am afraid I have never used the z argument, it is used internally, and you could in theory use it to speed up the process.
这篇关于技巧:使用宏填充数组值(代码生成)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:技巧:使用宏填充数组值(代码生成)
基础教程推荐
- GDB 显示调用堆栈上函数地址的当前编译二进制文 2022-09-05
- 通过引用传递 C++ 迭代器有什么问题? 2022-01-01
- 为什么 typeid.name() 使用 GCC 返回奇怪的字符以及如 2022-09-16
- 我应该对 C++ 中的成员变量和函数参数使用相同的名称吗? 2021-01-01
- CString 到 char* 2021-01-01
- 为什么 RegOpenKeyEx() 在 Vista 64 位上返回错误代码 2021-01-01
- 非静态 const 成员,不能使用默认赋值运算符 2022-10-09
- 为什么派生模板类不能访问基模板类的标识符? 2021-01-01
- 如果我为无符号变量分配负值会发生什么? 2022-01-01
- 初始化列表*参数*评估顺序 2021-01-01
