如何调用包含参数集的笛卡尔积中所有点的宏?

How can I invoke a macro with all points in a catersian product of argument sets?

假设我有一个宏

FOO(a, b)

我想用 a 的一组特定(固定)可能值调用此宏;和 b 的一组固定值。因此,如果我的 b 值集是 barbaz,而我的 b 值集是 fizbang,我想要:

FOO(bar, fiz)
FOO(bar, bang)
FOO(baz, fiz)
FOO(baz, bang)

由换行符或分号分隔,或两者兼而有之 - 这是一个小问题,所以让我们忽略它; 4 次调用的确切顺序也不重要。

现在,如果我只有一个 'dimension' 参数,我可以使用 William Swanson 的 mechanism (as described here on the site; and there's even a github repository),然后写

MAP(SINGLE_PARAMETER_MACRO, bar, baz, quux)

获得

SINGLE_PARAMETER_MACRO(bar)
SINGLE_PARAMETER_MACRO(baz)
SINGLE_PARAMETER_MACRO(quux)

但问题是,我有 两个 维度;似乎 impossible/tricky 将您的 __VA_ARGS__ 分成两个不同的集合,并从这些集合中迭代二维 space 元素对。

这可以(合理地)完成吗?

备注:

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

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 这里允许你这样做。

您可以轻松地将其扩展到更高维度的笛卡尔积。