Variadic макрос для создания структуры - PullRequest
0 голосов
/ 25 апреля 2018

Как я могу написать макрос (для gcc), который будет использоваться следующим образом:

CREATE_STRUCT(my_struct1,foo);
CREATE_STRUCT(my_struct2,foo,bar);

и расширяется до

struct my_struct1 {
     std::string foo;
};

struct my_struct2 {
     std::string foo;
     std::string bar;
};

?

Я, конечно,Мне нужна гибкость различного числа членов, но для меня уже подойдет небольшое число (что-то вроде 4 или 5).

Я нашел пару связанных вопросов, например this и это , но я полностью теряюсь, пытаясь применить такую ​​магию тайного макроса к этой проблеме.

PS: я знаю, как я мог бы написать 5 макросов (по одному на каждое число параметров)это сделало бы работу, поэтому на самом деле вопрос заключается в следующем: существует ли «простой» способ написания макроса с переменными числами, который выполняет эту работу?С другой стороны, я добавлю больше элементов в структуры, так что хранение всего этого в одном месте сэкономило бы много шаблонов.

Ответы [ 3 ]

0 голосов
/ 25 апреля 2018

Вот простая реализация, ограниченная пятью членами.

#define CREATE_STRUCT_IMPL_1(S1) std::string S1;
#define CREATE_STRUCT_IMPL_2(S1, ...) CREATE_STRUCT_IMPL_1(S1) CREATE_STRUCT_IMPL_1(__VA_ARGS__)
#define CREATE_STRUCT_IMPL_3(S1, ...) CREATE_STRUCT_IMPL_1(S1) CREATE_STRUCT_IMPL_2(__VA_ARGS__)
#define CREATE_STRUCT_IMPL_4(S1, ...) CREATE_STRUCT_IMPL_1(S1) CREATE_STRUCT_IMPL_3(__VA_ARGS__)
#define CREATE_STRUCT_IMPL_5(S1, ...) CREATE_STRUCT_IMPL_1(S1) CREATE_STRUCT_IMPL_4(__VA_ARGS__)

#define CREATE_STRUCT_IMPL(_1,_2,_3,_4,_5,NAME,...) NAME

#define CREATE_STRUCT(N, ...) struct N{ CREATE_STRUCT_IMPL(__VA_ARGS__, CREATE_STRUCT_IMPL_5, CREATE_STRUCT_IMPL_4, CREATE_STRUCT_IMPL_3, CREATE_STRUCT_IMPL_2, CREATE_STRUCT_IMPL_1)(__VA_ARGS__) }

Примеры

CREATE_STRUCT(my_struct1, foo);
CREATE_STRUCT(my_struct2, foo, bar);
CREATE_STRUCT(my_struct3, foo, bar, meow);
CREATE_STRUCT(my_struct4, foo, bar, meow, bazz);
CREATE_STRUCT(my_struct5, foo, bar, meow, bazz, dash);
0 голосов
/ 23 октября 2018

Это работает с любым количеством аргументов:

#define CREATE_STRUCT(N, ...) struct N { std::string __VA_ARGS__; }

Примеры:

CREATE_STRUCT(MyStruct, foo);
CREATE_STRUCT(MyStruct, foo, bar);
CREATE_STRUCT(MyStruct, foo, bar, baz);
0 голосов
/ 25 апреля 2018

Использование кода из Возможно ли перебирать аргументы в вариационных макросах?, вы можете сделать (жестко закодировано до 8 аргументов):

#define CONCATENATE(arg1, arg2)   CONCATENATE1(arg1, arg2)
#define CONCATENATE1(arg1, arg2)  CONCATENATE2(arg1, arg2)
#define CONCATENATE2(arg1, arg2)  arg1##arg2

#define FOR_EACH_1(what, x) what(x);
#define FOR_EACH_2(what, x, ...)\
  what(x);\
  FOR_EACH_1(what,  __VA_ARGS__)
#define FOR_EACH_3(what, x, ...)\
  what(x);\
  FOR_EACH_2(what, __VA_ARGS__)
#define FOR_EACH_4(what, x, ...)\
  what(x);\
  FOR_EACH_3(what,  __VA_ARGS__)
#define FOR_EACH_5(what, x, ...)\
  what(x);\
 FOR_EACH_4(what,  __VA_ARGS__)
#define FOR_EACH_6(what, x, ...)\
  what(x);\
  FOR_EACH_5(what,  __VA_ARGS__)
#define FOR_EACH_7(what, x, ...)\
  what(x);\
  FOR_EACH_6(what,  __VA_ARGS__)
#define FOR_EACH_8(what, x, ...)\
  what(x);\
  FOR_EACH_7(what,  __VA_ARGS__)

#define FOR_EACH_NARG(...) FOR_EACH_NARG_(__VA_ARGS__, FOR_EACH_RSEQ_N())
#define FOR_EACH_NARG_(...) FOR_EACH_ARG_N(__VA_ARGS__) 
#define FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, N, ...) N 
#define FOR_EACH_RSEQ_N() 8, 7, 6, 5, 4, 3, 2, 1, 0

#define FOR_EACH_(N, what, ...) CONCATENATE(FOR_EACH_, N)(what, __VA_ARGS__)
#define FOR_EACH(what, ...) FOR_EACH_(FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)

#define STRING_MEMBERS(x) std::string x

#define CREATE_STRUCT(name, ...) struct name { FOR_EACH(STRING_MEMBERS, __VA_ARGS__) }

CREATE_STRUCT(my_struct1, foo);
CREATE_STRUCT(my_struct2,foo,bar);
...