I am trying to force the evaluation of a macro parameter.
I tried to use the pattern in : Macro evaluation in c preprocessor
But for some reason here PP_NARG(VA_ARGS) does not expand correctly.
Do you know why the second line in main() is not compiling ?
error: pasting "RUN_CODE_FOR_EACH" and "(" does not give a valid preprocessing token
#define PP_NARG(...) (PP_NARG_(__VA_ARGS__,PP_RSEQ_N()) - \
(sizeof(#__VA_ARGS__) == 1))
#define PP_NARG_(...) PP_ARG_N(__VA_ARGS__)
#define PP_ARG_N( \
_1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \
_11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \
_21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \
_31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \
_41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \
_51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \
_61,_62,_63, N, ...) N
#define PP_RSEQ_N() \
63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9,8,7,6,5,4,3,2,1,0
#define RUN_CODE(code, x) { \
decltype(x) &&variadic_item = x; \
code; \
}
#define RUN_CODE_FOR_EACH1(code, x) RUN_CODE(code, x);
#define RUN_CODE_FOR_EACH2(code, x, ...) RUN_CODE(code, x); RUN_CODE_FOR_EACH1(code, __VA_ARGS__)
#define RUN_CODE_FOR_EACH3(code, x, ...) RUN_CODE(code, x); RUN_CODE_FOR_EACH2(code, __VA_ARGS__)
#define RUN_CODE_FOR_EACH4(code, x, ...) RUN_CODE(code, x); RUN_CODE_FOR_EACH3(code, __VA_ARGS__)
#define RUN_CODE_FOR_EACH5(code, x, ...) RUN_CODE(code, x); RUN_CODE_FOR_EACH4(code, __VA_ARGS__)
#define RUN_CODE_FOR_EACH6(code, x, ...) RUN_CODE(code, x); RUN_CODE_FOR_EACH5(code, __VA_ARGS__)
#define RUN_CODE_FOR_EACH7(code, x, ...) RUN_CODE(code, x); RUN_CODE_FOR_EACH6(code, __VA_ARGS__)
#define RUN_CODE_FOR_EACH8(code, x, ...) RUN_CODE(code, x); RUN_CODE_FOR_EACH7(code, __VA_ARGS__)
#define RUN_CODE_FOR_EACH__(code, size, ...) RUN_CODE_FOR_EACH##size(code, __VA_ARGS__)
#define RUN_CODE_FOR_EACH_(code, size, ...) RUN_CODE_FOR_EACH__(code, size, __VA_ARGS__)
#define RUN_CODE_FOR_EACH(code, ...) RUN_CODE_FOR_EACH_(code, PP_NARG(__VA_ARGS__), __VA_ARGS__)
void print(int i){std::cout << "int: " << i << '\n';}
int print(double d){std::cout << "double: " << d << '\n';return 2;}
int main() {
RUN_CODE_FOR_EACH_(print(variadic_item), 4, 1, 2., 3., 4); // Working
RUN_CODE_FOR_EACH(print(variadic_item), 1, 2., 3., 4); // Compilation error
std::cout << "size=" << PP_NARG(1, 2., 3., 4) << '\n'; // show size=4
return 0;
}
Thank you
PP_NARG does not make sense, as you're using compile-time constructs at preprocessor-time. You will not get a valid preprocessor-time argument count. You need to count the arguments without resorting to things like sizeof.
Here's an example on how that could be done from my vrm_pp library. First, I define the interface macros for argument counting:
#define VRM_PP_IMPL_N_ARG(...) VRM_PP_IMPL_NSEQ(__VA_ARGS__)
#define VRM_PP_IMPL_ARGCOUNT(...) \
VRM_PP_IMPL_N_ARG(__VA_ARGS__, VRM_PP_IMPL_RSEQ())
#define VRM_PP_ARGCOUNT(...) VRM_PP_IMPL_ARGCOUNT(__VA_ARGS__)
I then use a generator script to generate the count sequences.
VRM_PP_IMPL_RSEQ is a reverse-counting sequence: 10, 9, 8, 7, 6 ...
VRM_PP_IMPL_NSEQ is a macro that takes N arguments (where N is the maximum supported number of arguments) and returns the N-th argument.
You can find a complete explanation of this solution on the "C++ preprocessor __VA_ARGS__ number of arguments" question.
Related
So, I want to make a function(-like macro) that takes any number of arguments of different types and does something to it.
I mean, I did manage to make it work, but I'm looking for a more elegant solution (or to make sure my way is the way it should look like).
Example code of a function macro print(...):
#ifndef EVIL_PRINT_H
#define EVIL_PRINT_H
#include <stdio.h>
#define TWENTY_SECOND_ARGUMENT(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, ...) _22
#define COUNT_ARGUMENTS(...) TWENTY_SECOND_ARGUMENT(__VA_ARGS__, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define PRINT_CHAR_EVIL(x) printf("%c", x)
#define PRINT_INT_EVIL(x) printf("%i", x)
#define PRINT_FLOAT_EVIL(x) printf("%f", x)
#define PRINT_DOUBLE_EVIL(x) printf("%d", x)
#define PRINT_PTR_EVIL(x) printf("%p", x)
#define PRINT_STR_EVIL(x) printf("%s", x)
#define PRINT_ONE_EVIL(x, ...) _Generic(x, \
char: PRINT_CHAR_EVIL(x), \
int: PRINT_INT_EVIL(x), \
float: PRINT_FLOAT_EVIL(x), \
double: PRINT_DOUBLE_EVIL(x), \
void *: PRINT_PTR_EVIL(x), \
char const *: PRINT_STR_EVIL(x), \
char *: PRINT_STR_EVIL(x) \
)
#define PRINT_TWO_EVIL(_1, _2, ...) PRINT_ONE_EVIL(_1); PRINT_ONE_EVIL(_2)
...
#define PRINT_TWENTY_ONE_EVIL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, ...) PRINT_TWENTY_EVIL(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20); PRINT_ONE_EVIL(_21)
#define print(...) do { \
switch (COUNT_ARGUMENTS(__VA_ARGS__)) { \
default:break; \
case 1: \
PRINT_ONE_EVIL(__VA_ARGS__); \
break; case 2: \
PRINT_TWO_EVIL(__VA_ARGS__, 2); \
... \
break; case 21: \
PRINT_TWENTY_ONE_EVIL(__VA_ARGS__, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 18, 19, 20, 21); \
} \
} while(0);
#endif
My problem with this approach is that it copies a lot of code for one call, but I don't know, maybe the compiler optimizes all unneeded branches out. Also one limitation is that it will not accept more than x (in my case - 21) number of arguments. Adding more arguments is no big deal, but the file size is going to grow, if you need like 100+ arguments.
Usage example:
#include "evil_print.h"
int main(void) {
struct {
int i;
char c;
} v = {.i = 100, .c = 'A'}, o;
o = v;
print(v.i, ", ", o.c);
}
Yes, I know that it is easy in c++, don't mention that language here.
I'm looking for a more elegant solution
My most elegant solution, that I finally ended using for https://gitlab.com/Kamcuk/yio/ library, was to pass an array of function pointers that depend on the type of arguments. Such an array can be constructed inside the macro expansion with a compound literal and then passed to a dispatcher function. Because you are allowed to pass va_list via a pointer to the functions and then work on it, you can do type-specific operations inside the function pointers. The design is for limiting the use of preprocessor to the minimum, dispatching to function C side as early as possible.
#include <stdarg.h>
#include <stdio.h>
#include <limits.h>
#define APPLYFOREACH_1(f,a) f(a)
#define APPLYFOREACH_2(f,a,...) f(a) APPLYFOREACH_1(f,__VA_ARGS__)
#define APPLYFOREACH_3(f,a,...) f(a) APPLYFOREACH_2(f,__VA_ARGS__)
#define APPLYFOREACH_4(f,a,...) f(a) APPLYFOREACH_3(f,__VA_ARGS__)
#define APPLYFOREACH_N(_4,_3,_2,_1,N,...)\
APPLYFOREACH##N
#define APPLYFOREACH(f, ...) \
APPLYFOREACH_N(__VA_ARGS__,_4,_3,_2,_1)(f, ##__VA_ARGS__)
// ---------------------------------------------
// The main logic dispatcher.
typedef int (*lib_print_t)(va_list *va);
int lib_print_in_2(const lib_print_t *printers, va_list *va) {
int result = 0;
for (; *printers != NULL; ++printers) {
const int tmp = (*printers)(va);
if (tmp < 0) return tmp;
result += tmp;
}
return result;
}
int lib_print_in(const lib_print_t *printers, ...) {
va_list va;
va_start(va, printers);
const int ret = lib_print_in_2(printers, &va);
va_end(va);
return ret;
}
// ---------------------------------------------
// Type specific printers.
int lib_print_int(va_list *va) {
int c = va_arg(*va, int);
return printf("%d", c);
}
int lib_print_char(va_list *va) {
char c = va_arg(*va,
// char is promoted to int.... or is it?
// There are _many_ such cases to handle.
#if CHAR_MAX > INT_MAX
unsigned int
#else
int
#endif
);
return printf("%c", c);
}
int lib_print_charp(va_list *va) {
const char *c = va_arg(*va, char *);
return printf("%s", c);
}
int lib_print_float(va_list *va) {
// but float _is_ promoted to double
float c = va_arg(*va, double);
return printf("%f", c);
}
#define DISPATCH(x) \
_Generic((x) \
, int: lib_print_int \
, char: lib_print_char \
, char*: lib_print_charp \
, const char *: lib_print_charp \
, float: lib_print_float \
/* Note - comma on the end for below */ \
),
// ---------------------------------------------
// Calls lib_print_in with an array of function pointers
// and arguments.
#define lib_print(...) \
lib_print_in( \
(const lib_print_t []){ \
APPLYFOREACH(DISPATCH, __VA_ARGS__) \
NULL \
}, \
##__VA_ARGS__ \
)
// ---------------------------------------------
int main() {
lib_print(1, ", ", 1.0f, (char)'\n');
}
The code outputs 1, 1.000000.
Why do you pass function pointers instead of calling them right away?
To not abuse processor, so it nicely expands to a single function call, accumulate the result, correctly handle error, offer additional features like format string parsing. But sure, you can just call them right away if you do not care about such stuff. You would just do plain _Generic with a FOREACH macro, that's all.
#include <stdio.h>
#define APPLYFOREACH_1(f,a) f(a)
#define APPLYFOREACH_2(f,a,...) f(a) APPLYFOREACH_1(f,__VA_ARGS__)
#define APPLYFOREACH_3(f,a,...) f(a) APPLYFOREACH_2(f,__VA_ARGS__)
#define APPLYFOREACH_4(f,a,...) f(a) APPLYFOREACH_3(f,__VA_ARGS__)
#define APPLYFOREACH_N(_4,_3,_2,_1,N,...)\
APPLYFOREACH##N
#define APPLYFOREACH(f, ...) \
APPLYFOREACH_N(__VA_ARGS__,_4,_3,_2,_1)(f, ##__VA_ARGS__)
int lib_print_int(int c) {
printf("%d", c);
}
void lib_print_char(char c) {
printf("%c", c);
}
void lib_print_charp(const char *c) {
printf("%s", c);
}
void lib_print_float(float c) {
printf("%f", c);
}
#define lib_print_one(x) \
_Generic((x) \
, int: lib_print_int \
, char: lib_print_char \
, char*: lib_print_charp \
, const char *: lib_print_charp \
, float: lib_print_float \
)(x);
#define lib_print(...) do { \
APPLYFOREACH(lib_print_one, __VA_ARGS__) \
} while(0)
int main() {
lib_print(1, ", ", 1.0f, (char)'\n');
}
Note: _Generic is meant to be used like _Generic(x, int: functionpointers1, double: functionpointer2)(arguments, argument2). If you do _Generic(x, char: printf("%c", c) you should get a lot of compiler warnings of mismatched format string. It is easier with function pointers. In this case, you could also expand to printf(_Generic(x, char: "%c", int: "%d"), x), but I still like function pointers as much cleaner.
What I currently have
#define _CMPLT8 _mm_cmplt_epi8 // int8_t
#define _CMPLT32 _mm_cmplt_epi32 // int32_t
What I want (something similar to the following code)
#define _CMPLT(T) ( \
if(sizeof(T)==1) return _mm_cmplt_epi8 \
else if(sizeof(T)==4) return _mm_cmplt_epi32 \
else #error \
)
How could I this code?
If you want to return a string based on a type I'd go for generics:
#define _CMPLT(T) \
_Generic( (T), \
char: "1", \
int: "4", \
default: "0")
int main(void) {
char a;
int b;
printf("%s%s\n", _CMPLT(a), _CMPLT(b));
}
But I feel you want to call functions depending on arg type, so in that case:
#define _CMPLT(X, Y) _Generic((X), \
int8_t: _mm_cmplt_epi8(X, Y), \
int32_t: _mm_cmplt_epi32(X, Y) \
)
int main(void) {
int8_t a = 0, b = 1;
int32_t c = 2, d = 3;
printf("%d%d\n", _CMPLT(a, b), _CMPLT(c, d));
}
If you really need to use strings and sizeof, and can use compound statements, would this work for you?
#include <stdio.h>
#define _CMPLT(T) ({ \
switch(sizeof(T)) { \
case 1: "1"; \
case 4: "4"; \
}; \
"0"; \
})
int main(void) {
printf("%s%s\n",
_CMPLT(char), _CMPLT(int));
}
I would like to have a group of variable number of arguments passed into a macro. I have following macros which is incorrect:
#define M_NARGS(...) M_NARGS_(__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define M_NARGS_(_10, _9, _8, _7, _6, _5, _4, _3, _2, _1, N, ...) N
#define M_CONC(A, B) M_CONC_(A, B)
#define M_CONC_(A, B) A##B
#define M_ID(...) __VA_ARGS__
#define M_LEFT(L, R) L
#define M_RIGHT(L, R) R
#define M_FOR_EACH(ACTN, ...) M_CONC(M_FOR_EACH_, M_NARGS(__VA_ARGS__)) (ACTN, __VA_ARGS__)
#define M_FOR_EACH_0(ACTN, E) E
#define M_FOR_EACH_1(ACTN, E) ACTN(E)
#define M_FOR_EACH_2(ACTN, E, ...) ACTN(E) M_FOR_EACH_1(ACTN, __VA_ARGS__)
#define M_FOR_EACH_3(ACTN, E, ...) ACTN(E) M_FOR_EACH_2(ACTN, __VA_ARGS__)
#define M_FOR_EACH_4(ACTN, E, ...) ACTN(E) M_FOR_EACH_3(ACTN, __VA_ARGS__)
#define M_FOR_EACH_5(ACTN, E, ...) ACTN(E) M_FOR_EACH_4(ACTN, __VA_ARGS__)
#define FRUITS (apple, banana, cherry)
#define ANIMALS (dog, monkey)
#define ZOO_BLOCK(NAME, FRTS, ANMLS) struct NAME##Block { \
M_FOR_EACH(DEFINE_FRUITS, FRTS) \ // Wrong, see my question below
M_FOR_EACH(DEFINE_ANIMAL, ANMLS) \ // Wrong
}
#define DEFINE_FRUITS(F) Fruit F;
#define DEFINE_ANIMALS(F) Animal F;
ZOO_BLOCK(MyZoo, FRUITS, ANIMALS);
By M_FOR_EACH(DEFINE_FRUITS, FRTS), I would like to do M_FOR_EACH(DEFINE_FRUITS, __VA_ARGS__) actually and __VA_ARGS__ are all from FRUITS (i.e. apple, banana, cherry). How can I change my macros to do this?
I'm not sure whether this is what you are looking for, but the parenthesised fruit and animal groups are not resolved. You can "flatten" them with your M_IDmacro, e.g.:
#define M_ID(...) __VA_ARGS__
#define FRUITS M_ID(apple, banana, cherry)
#define ANIMALS M_ID(dog, monkey)
#define ZOO_BLOCK(NAME, FRTS, ANMLS) struct NAME##Block { \
M_FOR_EACH(DEFINE_FRUITS, FRTS) \
M_FOR_EACH(DEFINE_ANIMALS, ANMLS) \
}
#define DEFINE_FRUITS(F) Fruit F;
#define DEFINE_ANIMALS(F) Animal F;
ZOO_BLOCK(MyZoo, FRUITS, ANIMALS);
This, together with correcting a minor typo in DEFINE_ANIMAL/S yields:
struct MyZooBlock {
Fruit apple;
Fruit banana;
Fruit cherry;
Animal dog;
Animal monkey;
};
If you want to generate structs based on lists I would use higher order macros.
This does not require you to have another macro that actually does the loop resolution.
#define FRUITS(V) \
V(apple) \
V(banana) \
V(cherry)
#define ANIMALS(V) \
V(dog) \
V(monkey)
#define VISIT_ANI_STRUCT(A) \
Animal A;
#define VISIT_FRU_STRUCT(F) \
Fruit F;
#define ZOO_BLOCK(NAME, GEN_ANI,GEN_FRU) \
struct NAME ## Block { \
ANIMALS(GEN_ANI) \
FRUITS(GEN_FRU) \
}
ZOO_BLOCK(Zoo, VISIT_ANI_STRUCT, VISIT_FRU_STRUCT);
Will result in:
struct ZooBlock { Animal dog; Animal monkey; Fruit apple; Fruit banana; Fruit cherry; };
Or if you need the other way round
#define ZOO_BLOCK(NAME, A, F) \
struct NAME ## Block { \
A(VISIT_ANI_STRUCT) \
F(VISIT_FRU_STRUCT) \
}
ZOO_BLOCK(Zoo, VISIT_ANI_STRUCT, VISIT_FRU_STRUCT);
I'm trying to create a 'C' macro (not C++) that will define and initialize static data.
For example:
STATIC_CONST_STRUCT
(
A, a,
MEMBER_DATA(CONST_STR, a, "Hello, a")
MEMBER_DATA(CONST_STR, b, "Hello, b")
MEMBER_STRUCT
(
C, c,
MEMBER_DATA(CONST_STR, d, "Hello, d")
MEMBER_DATA(CONST_INT, e, 1)
)
);
Would cause the 'C' preprocessor to create:
static const struct A
{
CONST_STR a;
CONST_STR b;
struct C
{
CONST_STR d;
CONST_INT e;
} c;
} =
{"Hello, a", "Hello, b", {"Hello, d", 1}};
I've tried to use the Boost Preprocessor
http://www.boost.org/doc/libs/1_54_0/libs/preprocessor/doc/
but I can't quite figure out how to make this work. My macros stop expanding. I suspect the recursive nature of the problem having an arbitrarily deep nesting is why.
The solutions I read regarding getting the preprocessor to recurse either don't work, or the description of how to get recursion to work isn't clear enough to implement a working solution.
Here's what I have so far:
#define MEMBER_DATA_TAG 0
#define MEMBER_STRUCT_TAG 1
#define MEMBER_TAG(MEMBER) BOOST_PP_SEQ_ELEM(0, MEMBER)
#define MEMBER_DATA_TYPE(MEMBER_DATA) BOOST_PP_SEQ_ELEM(1, MEMBER_DATA)
#define MEMBER_DATA_NAME(MEMBER_DATA) BOOST_PP_SEQ_ELEM(2, MEMBER_DATA)
#define MEMBER_DATA_VALUE(MEMBER_DATA) BOOST_PP_SEQ_ELEM(3, MEMBER_DATA)
#define MEMBER_STRUCT_TYPE(MEMBER_STRUCT) BOOST_PP_SEQ_ELEM(1, MEMBER_STRUCT)
#define MEMBER_STRUCT_NAME(MEMBER_STRUCT) BOOST_PP_SEQ_ELEM(2, MEMBER_STRUCT)
#define MEMBER_STRUCT_MEMBER_SEQ(MEMBER_STRUCT) BOOST_PP_SEQ_ELEM(3, MEMBER_STRUCT)
#define MEMBER_DATA(TYPE, NAME, VALUE) ((MEMBER_DATA_TAG)(TYPE)(NAME)(VALUE))
#define MEMBER_STRUCT(TYPE, NAME, MEMBER_SEQ) ((MEMBER_STRUCT_TAG)(TYPE)(NAME)(MEMBER_SEQ))
#define IS_MEMBER_STRUCT(MEMBER_SEQ_ELEM) BOOST_PP_EQUAL(MEMBER_TAG(MEMBER_SEQ_ELEM), MEMBER_STRUCT_TAG)
#define MEMBER_STRUCT_DECLARE(TYPE, NAME, MEMBER_SEQ) \
struct TYPE \
{ \
BOOST_PP_SEQ_FOR_EACH(MEMBER_ELEM_DECLARE, BOOST_PP_EMPTY(), MEMBER_SEQ) \
} NAME
#define MEMBER_ELEM_DECLARE(_r, _data, MEMBER_SEQ_ELEM) \
BOOST_PP_IIF \
( \
IS_MEMBER_STRUCT(MEMBER_SEQ_ELEM), \
MEMBER_STRUCT_DECLARE \
( \
MEMBER_STRUCT_TYPE(MEMBER_SEQ_ELEM), \
MEMBER_STRUCT_NAME(MEMBER_SEQ_ELEM), \
MEMBER_STRUCT_MEMBER_SEQ(MEMBER_SEQ_ELEM) \
), \
MEMBER_DATA_DECLARE \
( \
MEMBER_DATA_TYPE(MEMBER_SEQ_ELEM), \
MEMBER_DATA_NAME(MEMBER_SEQ_ELEM), \
MEMBER_DATA_VALUE(MEMBER_SEQ_ELEM) \
) \
);
#define MEMBER_DATA_DECLARE(TYPE, NAME, VALUE) TYPE NAME
#define MEMBER_VALUE_INIT(MEMBER_SEQ) \
BOOST_PP_SEQ_FOR_EACH_I(MEMBER_VALUE_INIT_DECLARE, BOOST_PP_EMPTY(), MEMBER_SEQ);
#define MEMBER_VALUE_INIT_DECLARE(_r, _data, i, MEMBER_SEQ_ELEM) \
BOOST_PP_COMMA_IF(i) \
BOOST_PP_IIF \
( \
IS_MEMBER_STRUCT(MEMBER_SEQ_ELEM), \
{MEMBER_VALUE_INIT(MEMBER_SEQ_ELEM)}, \
MEMBER_DATA_VALUE(MEMBER_SEQ_ELEM) \
)
#define STATIC_CONST_STRUCT(TYPE, NAME, MEMBER_SEQ) \
static const MEMBER_STRUCT_DECLARE(TYPE, NAME, MEMBER_SEQ) = \
{ \
MEMBER_VALUE_INIT(MEMBER_SEQ) \
}
Thanks.
It can be done without boost-preprocessor.
You don't actually need recursion. Just a loop to iterate over the macro arguments twice.
I took liberty of modifying the syntax a bit, to allow for commas in types and initializers, in case someone decides to use it with C++.
STATIC_CONST_STRUCT
(
A, a,
MEMBER_DATA(a, const char *) "Hello, a"
MEMBER_DATA(b, const char *) "Hello, b"
MEMBER_STRUCT
(
C, c,
MEMBER_DATA(d, const char *) "Hello, d"
MEMBER_DATA(e, int) 42
)
)
This expands to:
static const struct A
{
const char *a;
const char *b;
struct C
{
const char *d;
int e;
} c;
} a =
{
"Hello, a",
"Hello, b",
{
"Hello, d",
42,
},
};
Implementation:
#define STATIC_CONST_STRUCT(type_, name_, ...) \
static const struct type_ { \
END( LOOP_DECL_0 (__VA_ARGS__) ) \
} name_ = { \
END( LOOP_INIT_0 (__VA_ARGS__) ) \
};
#define MEMBER_DATA(name_, ...) )(var,name_,(__VA_ARGS__),
#define MEMBER_STRUCT(type_, name_, ...) )(open,type_ __VA_ARGS__ )(close,name_
#define IDENTITY(...) __VA_ARGS__
#define CAT(x, y) CAT_(x, y)
#define CAT_(x, y) x##y
#define END(...) END_(__VA_ARGS__)
#define END_(...) __VA_ARGS__##_END
#define LOOP_DECL_0() LOOP_DECL_A
#define LOOP_DECL_A(...) LOOP_DECL_BODY(__VA_ARGS__) LOOP_DECL_B
#define LOOP_DECL_B(...) LOOP_DECL_BODY(__VA_ARGS__) LOOP_DECL_A
#define LOOP_DECL_0_END
#define LOOP_DECL_A_END
#define LOOP_DECL_B_END
#define LOOP_DECL_BODY(action_, ...) CAT(LOOP_DECL_BODY_, action_)(__VA_ARGS__)
#define LOOP_DECL_BODY_var(name_, type_, ...) IDENTITY type_ name_;
#define LOOP_DECL_BODY_open(type_) struct type_ {
#define LOOP_DECL_BODY_close(name_) } name_;
#define LOOP_INIT_0() LOOP_INIT_A
#define LOOP_INIT_A(...) LOOP_INIT_BODY(__VA_ARGS__) LOOP_INIT_B
#define LOOP_INIT_B(...) LOOP_INIT_BODY(__VA_ARGS__) LOOP_INIT_A
#define LOOP_INIT_0_END
#define LOOP_INIT_A_END
#define LOOP_INIT_B_END
#define LOOP_INIT_BODY(action_, ...) CAT(LOOP_INIT_BODY_, action_)(__VA_ARGS__)
#define LOOP_INIT_BODY_var(name_, type_, ...) __VA_ARGS__,
#define LOOP_INIT_BODY_open(type_) {
#define LOOP_INIT_BODY_close(name_) },
If used with C++, IDENTITY type_ should be wrapped in std::type_identity_t<...> to allow using types such as function pointers without typedefing them. void (*)() foo; is illegal, while std::type_identity_t<void (*)()> foo; is ok.
I want to define a macro accepting either 1 or 2 parameters. Both the parameters should be different type. How to use ellipsis and read the arguments passed?
Below is the sample:
void test(char *var2)
{
printf("%s\n",var2);
}
#define PRINT_STRING(...) ( if (!var1) test(var2) )
int main(int argc, _TCHAR argv[]) {
PRINT_STRING(TRUE);
PRINT_STRING(FALSE,"Hello, World!");
return 0;
}
This is known as a Variadic macro.
If your compiler supports __VA_ARGS__, you can do it like this:
#include <stdio.h>
#define NUM_ARGS__(X, \
N64,N63,N62,N61,N60, \
N59,N58,N57,N56,N55,N54,N53,N52,N51,N50, \
N49,N48,N47,N46,N45,N44,N43,N42,N41,N40, \
N39,N38,N37,N36,N35,N34,N33,N32,N31,N30, \
N29,N28,N27,N26,N25,N24,N23,N22,N21,N20, \
N19,N18,N17,N16,N15,N14,N13,N12,N11,N10, \
N09,N08,N07,N06,N05,N04,N03,N02,N01, N, ...) N
#define NUM_ARGS(...) \
NUM_ARGS__(0, __VA_ARGS__, \
64,63,62,61,60, \
59,58,57,56,55,54,53,52,51,50, \
49,48,47,46,45,44,43,42,41,40, \
39,38,37,36,35,34,33,32,31,30, \
29,28,27,26,25,24,23,22,21,20, \
19,18,17,16,15,14,13,12,11,10, \
9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define PRINT_STRING_1(var) \
{ if (!(var)) {} }
#define PRINT_STRING_2(var, ...) \
{ if (!(var)) test(__VA_ARGS__); }
#define PRINT_STRINGN__(N, ...) \
PRINT_STRING_##N(__VA_ARGS__)
#define PRINT_STRINGN(N, ...) \
PRINT_STRINGN__(N, __VA_ARGS__)
#define PRINT_STRING(...) \
PRINT_STRINGN(NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
void test(char* var2)
{
printf("%s\n", var2);
}
int main(void)
{
PRINT_STRING(1);
PRINT_STRING(0, "Hello, World!");
PRINT_STRING(1, "You can't see me!");
return 0;
}
Output:
Hello, World!
To do something like that you'd have to implement a series of macros, something like this
#include <stdbool.h>
#define PRINT_STRING0(X, Y) do { if (X && Y) test(Y); } while(false)
#define PRINT_STRING1(X, Y, ...) PRINT_STRING0(X, Y)
#define PRINT_STRING(...) PRINT_STRING1(__VA_ARGS__, 0, 0)
The last of them (user interface) adds a second or third argument of 0. PRINT_STRING1 then ignores all arguments that are more than 2. And PRINT_STRING0 then does the work.
Some more remarks:
be careful that a macro like you want to program it here can be place syntactically just as any other statement. In the example here the do { } while(false) does that trick
since C99 has Boolean type and constants, these are _Bool or bool and false and true
Don't use a macro to do that, use a variadic function!
void print_string( bool should_print, ... )
{
if( should_print )
{
va_list argp;
va_start( argp, should_print);
char *string = va_arg(argp, char *);
if( string) printf("%s", string );
va_end( argp );
}
}
But be very careful when using these sorts of things, because va_arg doesn't check if you really have a 2nd argument.
Also, to use a macro that accepts one or 2 arguments, use the GCC trick (at the very bottom of this page):
#define PRINT_STRING( should , args... ) print_string( should , ##args )
(note the spaces between the commas)