预处理器宏调用所有可能的组合
Preprocessor macro calling all possible combinations
我创建了一个包含 3 个条件的宏(例如,在我的真实情况下是 8 个):
#define FOO(A,B,C) \
BOOST_PP_IF(A, a1, a2) \
BOOST_PP_IF(B, b1, b2) \
BOOST_PP_IF(C, c1, c2)
这符合我的预期。现在我想展开所有的可能性:
FOO(0,0,0)
FOO(0,0,1)
FOO(0,1,0)
FOO(0,1,1)
FOO(1,0,0)
FOO(1,0,1)
FOO(1,1,0)
FOO(1,1,1)
这么一来,我得写8行。在我的实际情况下,我必须写 256 行。
如何使用(增强)预处理器工具直接生成它?
构造函数声明的 MCV 示例 class Foo
接近我的实际问题:
#define WRITE_FOO(A,B,C) \
Foo(int a1 BOOST_PP_COMMA_IF(A) BOOST_PP_IF(A, int a2, BOOST_PP_EMPTY()),
double b1 BOOST_PP_COMMA_IF(B) BOOST_PP_IF(B, double b2, BOOST_PP_EMPTY()),
bool c1 BOOST_PP_COMMA_IF(C) BOOST_PP_IF(C, bool c2, BOOST_PP_EMPTY()));
然后
class Foo {
public:
WRITE_FOO(0,0,0)
WRITE_FOO(0,0,1)
WRITE_FOO(0,1,0)
WRITE_FOO(0,1,1)
WRITE_FOO(1,0,0)
WRITE_FOO(1,0,1)
WRITE_FOO(1,1,0)
WRITE_FOO(1,1,1)
private:
int a_1;
int a_2;
double b_1;
double b_2;
bool c_1;
bool c_2;
};
扩展为
class Foo {
public:
Foo(int a1, double b1, bool c1);
Foo(int a1, double b1, bool c1, bool c2);
Foo(int a1, double b1, double b2, bool c1);
Foo(int a1, double b1, double b2, bool c1, bool c2);
Foo(int a1, int a2, double b1, bool c1);
Foo(int a1, int a2, double b1, bool c1, bool c2);
Foo(int a1, int a2, double b1, double b2, bool c1);
Foo(int a1, int a2, double b1, double b2, bool c1, bool c2);
private:
int a_1;
int a_2;
double b_1;
double b_2;
bool c_1;
bool c_2;
};
实现类似于:
#define IMPLEMENT_FOO(A,B,C) \
Foo::Foo(int a1 BOOST_PP_COMMA_IF(A) BOOST_PP_IF(A, int a2, BOOST_PP_EMPTY()),
double b1 BOOST_PP_COMMA_IF(B) BOOST_PP_IF(B, double b2, BOOST_PP_EMPTY()),
bool c1 BOOST_PP_COMMA_IF(C) BOOST_PP_IF(C, bool c2, BOOST_PP_EMPTY())): \
a_1(a1), \
a_2(BOOST_PP_IF(A, a2, a1)), \
b_1(b1),
b_2(BOOST_PP_IF(B, b2, b1)), \
c_1(c1),
c_2(BOOST_PP_IF(C, c2, c1)) \
{}
这是解决问题的线性代码解决方案(尽管我不建议在实际代码中这样做,如果可能,请使用 template
s)
#define W2(...) W1(__VA_ARGS__,0) W1(__VA_ARGS__,1)
#define W1(...) W0(__VA_ARGS__,0) W0(__VA_ARGS__,1)
W2(0) W2(1)
不直接回答你的问题(这不使用宏),但你可以使用模板元编程解决你的问题。
不幸的是,可变参数模板是 C++11 的一项功能。 This question contain more details about how to implement them for C++03 with pure C++, or 有提升。
还需要线性代码。
struct F{
int i1,i2,d1,d2;
template<class... Args>
F(Args... args){init(args...);}
void init(){} // base case
template<class... Args>
void init(int i1_,Args... args){i1=i1_;i2=i1_;init(args...);}
template<class... Args>
void init(int i1_,int i2_,Args... args){i1=i1_;i2=i2_;init(args...);}
template<class... Args>
void init(double d1_,Args... args){d1=d1_;d2=d1_;init(args...);}
template<class... Args>
void init(double d1_,double d2_,Args... args){d1=d1_;d2=d2_;init(args...);}
};
Try it online! (gcc) or Try it online!(当当)
要求类型是可分配的。如果您担心效率,您可能想添加一些 std::move
。
我创建了一个包含 3 个条件的宏(例如,在我的真实情况下是 8 个):
#define FOO(A,B,C) \
BOOST_PP_IF(A, a1, a2) \
BOOST_PP_IF(B, b1, b2) \
BOOST_PP_IF(C, c1, c2)
这符合我的预期。现在我想展开所有的可能性:
FOO(0,0,0)
FOO(0,0,1)
FOO(0,1,0)
FOO(0,1,1)
FOO(1,0,0)
FOO(1,0,1)
FOO(1,1,0)
FOO(1,1,1)
这么一来,我得写8行。在我的实际情况下,我必须写 256 行。
如何使用(增强)预处理器工具直接生成它?
构造函数声明的 MCV 示例 class Foo
接近我的实际问题:
#define WRITE_FOO(A,B,C) \
Foo(int a1 BOOST_PP_COMMA_IF(A) BOOST_PP_IF(A, int a2, BOOST_PP_EMPTY()),
double b1 BOOST_PP_COMMA_IF(B) BOOST_PP_IF(B, double b2, BOOST_PP_EMPTY()),
bool c1 BOOST_PP_COMMA_IF(C) BOOST_PP_IF(C, bool c2, BOOST_PP_EMPTY()));
然后
class Foo {
public:
WRITE_FOO(0,0,0)
WRITE_FOO(0,0,1)
WRITE_FOO(0,1,0)
WRITE_FOO(0,1,1)
WRITE_FOO(1,0,0)
WRITE_FOO(1,0,1)
WRITE_FOO(1,1,0)
WRITE_FOO(1,1,1)
private:
int a_1;
int a_2;
double b_1;
double b_2;
bool c_1;
bool c_2;
};
扩展为
class Foo {
public:
Foo(int a1, double b1, bool c1);
Foo(int a1, double b1, bool c1, bool c2);
Foo(int a1, double b1, double b2, bool c1);
Foo(int a1, double b1, double b2, bool c1, bool c2);
Foo(int a1, int a2, double b1, bool c1);
Foo(int a1, int a2, double b1, bool c1, bool c2);
Foo(int a1, int a2, double b1, double b2, bool c1);
Foo(int a1, int a2, double b1, double b2, bool c1, bool c2);
private:
int a_1;
int a_2;
double b_1;
double b_2;
bool c_1;
bool c_2;
};
实现类似于:
#define IMPLEMENT_FOO(A,B,C) \
Foo::Foo(int a1 BOOST_PP_COMMA_IF(A) BOOST_PP_IF(A, int a2, BOOST_PP_EMPTY()),
double b1 BOOST_PP_COMMA_IF(B) BOOST_PP_IF(B, double b2, BOOST_PP_EMPTY()),
bool c1 BOOST_PP_COMMA_IF(C) BOOST_PP_IF(C, bool c2, BOOST_PP_EMPTY())): \
a_1(a1), \
a_2(BOOST_PP_IF(A, a2, a1)), \
b_1(b1),
b_2(BOOST_PP_IF(B, b2, b1)), \
c_1(c1),
c_2(BOOST_PP_IF(C, c2, c1)) \
{}
这是解决问题的线性代码解决方案(尽管我不建议在实际代码中这样做,如果可能,请使用 template
s)
#define W2(...) W1(__VA_ARGS__,0) W1(__VA_ARGS__,1)
#define W1(...) W0(__VA_ARGS__,0) W0(__VA_ARGS__,1)
W2(0) W2(1)
不直接回答你的问题(这不使用宏),但你可以使用模板元编程解决你的问题。
不幸的是,可变参数模板是 C++11 的一项功能。 This question contain more details about how to implement them for C++03 with pure C++, or
还需要线性代码。
struct F{
int i1,i2,d1,d2;
template<class... Args>
F(Args... args){init(args...);}
void init(){} // base case
template<class... Args>
void init(int i1_,Args... args){i1=i1_;i2=i1_;init(args...);}
template<class... Args>
void init(int i1_,int i2_,Args... args){i1=i1_;i2=i2_;init(args...);}
template<class... Args>
void init(double d1_,Args... args){d1=d1_;d2=d1_;init(args...);}
template<class... Args>
void init(double d1_,double d2_,Args... args){d1=d1_;d2=d2_;init(args...);}
};
Try it online! (gcc) or Try it online!(当当)
要求类型是可分配的。如果您担心效率,您可能想添加一些 std::move
。