假设我有一个宏
FOO(a, b)
我希望使用a
的某个(固定)可能值集来调用此宏;以及b
的一组固定值。因此,如果我的b值为bar
和baz
且我的b值为fiz
和bang
,我想要:
FOO(bar, fiz)
FOO(bar, bang)
FOO(baz, fiz)
FOO(baz, bang)
用新行或分号或两者分隔 - 这是一个小问题,所以让我们忽略它; 4次调用的确切顺序也不重要。
现在,如果我只有一个维度'参数,我可以使用威廉斯旺森的mechanism(如网站上所述;其中甚至还有github repository),然后写
MAP(SINGLE_PARAMETER_MACRO, bar, baz, quux)
获取
SINGLE_PARAMETER_MACRO(bar)
SINGLE_PARAMETER_MACRO(baz)
SINGLE_PARAMETER_MACRO(quux)
但问题是,我有两个维度;将__VA_ARGS__
分成两个不同的集合,并从这些集合中迭代元素对的二维空间似乎是不可能/棘手的。
这可以(合理地)完成吗?
备注:
答案 0 :(得分:3)
BOOST_REPEAT_PP
可以帮到你。
例如,如果您有两个数字数组,则可以在c ++ 14中执行此操作:
#include <boost/preprocessor/repetition/repeat.hpp>
#include <array>
#include <iostream>
constexpr std::array<int, 2> a = {2, 4};
constexpr std::array<int, 3> b = {1, 3, 7};
#define MYNUMBER2(z, n, x) std::cout << a[x] << " " << b[n] << std::endl;
#define MYNUMBER(z, n, x) BOOST_PP_REPEAT(3, MYNUMBER2, n)
int main() {
BOOST_PP_REPEAT(2, MYNUMBER, 0); // The "0" is actually not used
}
输出:
2 1
2 3
2 7
4 1
4 3
4 7
如果您不想使用std::array
,您还可以采用以下方法(不需要c ++ 14):
#include <boost/preprocessor/repetition/repeat.hpp>
#include <iostream>
#define A_0 "bar"
#define A_1 "baz"
#define A_2 "ban"
#define B_0 "fiz"
#define B_1 "bang"
#define FOO(s1, s2) std::cout << s1 << " " << s2 << std::endl;
#define MYSTRING2(z, n, x) FOO(A_##x, B_##n)
#define MYSTRING(z, n, x) BOOST_PP_REPEAT(2, MYSTRING2, n)
int main() {
BOOST_PP_REPEAT(3, MYSTRING, 0); // The "0" is actually not used
}
输出:
bar fiz
bar bang
baz fiz
baz bang
ban fiz
ban bang
答案 1 :(得分:1)
boost预处理器库可以在预处理器列表和序列上执行笛卡尔积。您没有指定要输入的预处理器数据类型...假设A和B是元组,并且您有可变参数,您可以这样做:
#include <boost/preprocessor/seq/for_each_product.hpp>
#include <boost/preprocessor/seq/to_tuple.hpp>
#include <boost/preprocessor/tuple/to_seq.hpp>
#define EVAL(...) __VA_ARGS__
#define FOO_SEMI_DELIM(R,SEQ_X) EVAL(FOO BOOST_PP_SEQ_TO_TUPLE(SEQ_X));
#define FOO_CARTESIAN(TUP_A,TUP_B) \
BOOST_PP_SEQ_FOR_EACH_PRODUCT \
( FOO_SEMI_DELIM, \
(BOOST_PP_TUPLE_TO_SEQ(TUP_A)) \
(BOOST_PP_TUPLE_TO_SEQ(TUP_B)) \
)
FOO_CARTESIAN((John,Jane),(Smith,Jones,Parker,Peterson))
由于FOO
全部上限,我假设您想结束将FOO称为宏; EVAL
允许您执行此操作。
您可以轻松将其扩展到更高尺寸的笛卡尔积。