Search code examples
c++c-preprocessorboost-preprocessor

Preprocessor macro calling all possible combinations


I created a macro taking 3 conditions (as example, 8 in my real case):

#define FOO(A,B,C) \
  BOOST_PP_IF(A, a1, a2) \
  BOOST_PP_IF(B, b1, b2) \
  BOOST_PP_IF(C, c1, c2)

This works as I expect. Now I want to expand all the possibilities:

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)

By this way, I have to write 8 lines. In my real case, I have to write 256 lines.

How can I generate it directly with (boost) preprocessor tools ?

MCV example with constructors declaration of a class Foo close to my real problem:

#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()));

Then

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;
};

is extended to

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;
};

The implementation is similar to:

#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)) \
{}

Solution

  • This is a linear-code solution that solves the question (although I would not suggest doing that in real code, use templates instead if possible)

    #define W2(...) W1(__VA_ARGS__,0) W1(__VA_ARGS__,1)
    #define W1(...) W0(__VA_ARGS__,0) W0(__VA_ARGS__,1)
    W2(0) W2(1)
    

    Try it online!