Макрос препроцессора, вызывающий все возможные комбинации - PullRequest
0 голосов
/ 14 мая 2018

Я создал макрос, используя 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 с объявлением конструкторов aкласс 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)) \
{}

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

Непосредственно не отвечайте на ваш вопрос (здесь не используются макросы), но вместо этого вы можете решить свою проблему, используя шаблонное метапрограммирование.

К сожалению, шаблон variadic является функцией C ++ 11. Этот вопрос содержит более подробную информацию о том, как реализовать их для C ++ 03 с чистым C ++ или этот вопрос с Boost.

Также требуется линейный код.

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

};

Попробуйте онлайн! (gcc) или Попробуйте онлайн! (лязг)

Требует назначения типов. Вы можете добавить std::move, если вы беспокоитесь об эффективности.

0 голосов
/ 14 мая 2018

Это решение с линейным кодом, которое решает вопрос (хотя я бы не советовал делать это в реальном коде, вместо этого используйте 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)

Попробуйте онлайн!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...