How can I write a macro (for gcc) that would be used like this:
CREATE_STRUCT(my_struct1,foo);
CREATE_STRUCT(my_struct2,foo,bar);
and expands to
struct my_struct1 {
std::string foo;
};
struct my_struct2 {
std::string foo;
std::string bar;
};
?
I certainly do need the flexibility of different number of members, but already a small number would be fine for me (something like 4 or 5).
I found a couple of related questions, eg this and this, but I am completely lost when trying to apply such arcane macro magic to this problem.
PS: I know how I could write 5 macros (one for each number of params) that would do the job, so actually the question is: Is there an "easy" way to write a variadic macro that does the job? On the other hand, I will add more stuff to the structs, so having it all in one place would save lots of boilerplate.
To use variadic macros, the ellipsis may be specified as the final formal argument in a macro definition, and the replacement identifier __VA_ARGS__ may be used in the definition to insert the extra arguments. __VA_ARGS__ is replaced by all of the arguments that match the ellipsis, including commas between them.
Preprocessor: __VA_ARGS__ (Variadic macros) If the parameters of a macro contain three consecutive dots ( ... ), this indicates that an arbitrary number of parameters may be passed. In the macro expansion, these values that are then referenced by the special identifier __VA_ARGS__ .
The variable argument is completely macro-expanded before it is inserted into the macro expansion, just like an ordinary argument. You may use the ' # ' and ' ## ' operators to stringize the variable argument or to paste its leading or trailing token with another token.
We can use printf() function in a Macro. In this example, we are creating a function like Macro that will print the result of a calculation, like adding two numbers.
Variadic macros are function-like macros that contain a variable number of arguments. To use variadic macros, the ellipsis may be specified as the final formal argument in a macro definition, and the replacement identifier __VA_ARGS__ may be used in the definition to insert the extra arguments.
// Count how many args are in a variadic macro. Only works for up to N-1 args. See how it works? The first macro, _GET_NTH_ARG (), takes any number of args >= N, but always returns item N (in this case, N =5).
* Provide a for-each construct for variadic macros. Supports up * to 4 args. #define CALL_MACRO_X_FOR_EACH (x, …)
This tutorial will demonstrate how to use structures in VBA. A structure in VBA is essentially a user-defined data type. When we use variables in VBA, we can declare them a string variable, number variables etc. Creating a structure essentially creates a new variable type, the structure itself can contain multiple data types.
Using code from Is it possible to iterate over arguments in variadic macros? , you may do (Hard coded up to 8 arguments):
#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);
This works with any number of arguments:
#define CREATE_STRUCT(N, ...) struct N { std::string __VA_ARGS__; }
Examples:
CREATE_STRUCT(MyStruct, foo);
CREATE_STRUCT(MyStruct, foo, bar);
CREATE_STRUCT(MyStruct, foo, bar, baz);
Here is simple implementation, limited to five members.
#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__) }
Examples
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);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With