问题描述
我在阅读上面的主题,突然这个想法来到我的脑海:为什么不尝试写它可以在我们的现实code使用一些棘手的宏(而不只是仅作为拼图这是在现实生活中毫无用处)?
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
在线演示:
我们能否进一步提高紧凑或通用性方面该解决方案(可能两者都有)?我们可以摆脱变量 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时有效code ++和C(当然忽略印刷部分)?
I would also like to know if that is valid code both in C++ and C (of course ignoring printing part)?
编辑:
我意识到,调用的顺序 F()
似乎仍的未指定的。我不知道,虽然,因为我认为逗号阵列初始化的不的可能一样逗号(一般)。但是,如果是这样,我们才能避免它,什么标准的一部分表示,其的未指定的?
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?
推荐答案
如果你想深入到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.
例如,为了创建表,我会用():
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 << "\n";
for(std::size_t i = 0 ; i != n ; ++i )
std::cout << a[i] << "\n";
return 0;
}
和离开所有的克鲁夫特,以提高:)
And leave all the cruft to Boost :)
注意:此列举0〜99,而不是1至100,有可用于执行算术其它操作)的
编辑:如何做到这一点的工作。
How does this work ?
首先,我只能推荐的
BOOST_PP_ENUM
是一个宏包含3个参数:(N,万家乐,数据)
BOOST_PP_ENUM
is a macro which takes 3 arguments: (n, MACRO, data)
-
N
:整数 -
MACRO
:宏接受3个参数:(Z,I,数据)
-
数据
:一些数据,您方便的,要传递给宏
n
: an integerMACRO
: a macro accepting 3 arguments:(z, i, data)
data
: some data, of your convenience, to be passed tomacro
那么通过 MACRO
用逗号分隔的n个连续的调用被替换
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
。
我怕我从来没有使用了以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.
这篇关于绝招:灌装使用宏数组值(code代)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!