How to define same macro function based on different parameters - c++

#define UPUT_SET_CHECK_POINT1(appType, tag, argNum1, v1, ...) \
if(NUMARGS(##__VA_ARGS__) == 0) \
UPUT_SET_CHECK_POINTx(1, appType, tag, argNum1, v1, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, __FILE__, __LINE__, UPUT_SEQUENTIAL); \
else \
UPUT_SET_CHECK_POINTx(1, appType, tag, argNum1, v1, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, UPUT_P_INVALID, 0, __FILE__, __LINE__ , __VA_ARGS__)
so when VA_ARGS is empty I am getting a compile time error "expected primary-expression before ')' token". Any way to fix the compilation error.
void UPUT_SET_CHECK_POINTx(int numArg, CtblAppType appType, int tag, UputArgPos argNum1, int v1, UputArgPos argNum2, int v2, UputArgPos argNum3, int v3, UputArgPos argNum4, int v4, UputArgPos argNum5, int v5, char* fileName, unsigned int lineNumber, UputCheckPointAlgo checkPointAlgo=UPUT_SEQUENTIAL);

If you are using GCC, you could use , ## __VA_ARGS__ to eliminate the comma when __VA_ARGS__ is empty.
#define UPUT_SET_CHECK_POINT1(appType, tag, argNum1, v1, ...) \
UPUT_SET_CHECK_POINTx(1, appType, tag, argNum1, v1, \
UPUT_P_INVALID, 0, \
UPUT_P_INVALID, 0, \
UPUT_P_INVALID, 0, \
UPUT_P_INVALID, 0, \
__FILE__, __LINE__ , ## __VA_ARGS__)
See also Standard alternative to GCC's ##__VA_ARGS__ trick?. There's no standard workaround to this if you have to use preprocessors.

Related

Error in macro with __VA_OPT__ and parenthesis

I am using c++,gcc. I have code for logging with macro like this:
#define E_DEBUG(level, ...) \
if (err_get_debug_level() >= level) \
err_msg(ERR_DEBUG, FILELINE, __VA_OPT__)
#define ERR_DEBUG 1
#define FILELINE __FILE__ , __LINE__
int err_get_debug_level(void);
void err_msg(int lvl, const char *path, long ln, const char *fmt, ...);
int main ( void ) {
E_DEBUG(1,("%d",14));
}
The code give an error VA_OPT must be followed by an open parenthesis
I change the code according this Error in macro with __va_args__ and parenthesis.
The code look like:
#define PASTE(...) __VA_OPT__
#define E_DEBUG(level, ...) \
if (err_get_debug_level() >= level) \
err_msg(ERR_DEBUG, FILELINE, PASTE __VA_OPT__)
#define ERR_DEBUG 1
#define FILELINE __FILE__ , __LINE__
int err_get_debug_level(void);
void err_msg(int lvl, const char *path, long ln, const char *fmt, ...);
int main ( void ) {
E_DEBUG(1,("%d",14));
}
It gives an error unterminated VA_OPT. How should I fix it?
__VA_OPT__ is used to conditionally insert something in your macro, it's not equivalent to __VA_ARGS__, you need both:
#define E_DEBUG(level, ...) \
if (err_get_debug_level() >= level) \
err_msg(ERR_DEBUG, FILELINE __VA_OPT__(,) __VA_ARGS__)
This will not compile with your code because you used ("%d", 14) and I don't really understand why. If you remove the extra brackets, the code compiles.

Tracking User-Defined `struct` Members with a Designated Initializer Syntax

For a unit-testing library that I'm writing, rexo, I would like to implement an automatic test registration mechanism compatible with both C99 and C++11.
Automatic test registration usually goes along the lines of:
providing macros for the users to define test suites and test cases.
having the macros instantiate file-level structures that contain the data needed to fully describe their respective test suites/cases.
having some logic that can somehow discover these structure instances at run-time.
I've got most of this sorted out but one bit: providing a nice interface for defining additional data to be attached to each test suite/case.
The (non-public) data structure to attach looks like this:
struct rx__data {
const char *name;
int value;
rx_run_fn run;
};
I managed to get a RX__MAKE_DATA() macro working with a designated initializer syntax, as follows:
/* https://github.com/swansontec/map-macro ----------------------------------- */
#define EVAL0(...) __VA_ARGS__
#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
#define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL4(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__)))
#define MAP_END(...)
#define MAP_OUT
#define MAP_GET_END2() 0, MAP_END
#define MAP_GET_END1(...) MAP_GET_END2
#define MAP_GET_END(...) MAP_GET_END1
#define MAP_NEXT0(test, next, ...) next MAP_OUT
#define MAP_NEXT1(test, next) MAP_NEXT0(test, next, 0)
#define MAP_NEXT(test, next) MAP_NEXT1(MAP_GET_END test, next)
#define MAP0(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP1)(f, peek, __VA_ARGS__)
#define MAP1(f, x, peek, ...) f(x) MAP_NEXT(peek, MAP0)(f, peek, __VA_ARGS__)
#define MAP(f, ...) EVAL(MAP1(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))
/* -------------------------------------------------------------------------- */
typedef int (*rx_run_fn)();
struct rx__data {
const char *name;
int value;
rx_run_fn run;
};
int run() { return 999; }
#ifdef __cplusplus
#define RX__WRAP_ASSIGNMENT(x) out x;
#define RX__MAKE_DATA(...) \
[]() -> struct rx__data { \
struct rx__data out = {}; \
MAP(RX__WRAP_ASSIGNMENT, __VA_ARGS__); \
return out; \
}()
#else
#define RX__MAKE_DATA(...) { __VA_ARGS__ }
#endif
static const struct rx__data foo
= RX__MAKE_DATA(.name = "abc", .value = 123, .run = run);
It's all good except that, since the rx__data struct can be attached to both test suites and test cases, I'd like to have a mechanism that allows me to know if a data member has been explicitely set or not by the user. This way, I can infer the final data to apply to a test case by:
retrieving the data to inherit from the parent test suite.
overriding only the members from the test suite that were explicitely set onto the test case.
For example
RX_TEST_SUITE(my_suite, .name = "abc", .value = 123, .run = run);
RX_TEST_CASE(my_suite, my_case, .value = 666)
{
...
}
would result in ‘my_case’ having the data {.name = "abc", .value = 666, .run = run} attached to it.
For this to work, I thought of adding a boolean value for each field, to keep track of what has been explicitely defined or not by the user:
typedef int (*rx_run_fn)();
struct rx__data {
const char *name;
int value;
rx_run_fn run;
int name_defined;
int value_defined;
int run_defined;
};
int run() { return 999; }
#ifdef __cplusplus
#define RX__ARG(field, value) out.field = value; out.field##_defined = 1
#define RX__MAKE_DATA(...) \
[]() -> struct rx__data { \
struct rx__data out = {}; \
__VA_ARGS__; \
return out; \
}();
#else
#define RX__ARG(field, value) .field = value, .field##_defined = 1
#define RX__MAKE_DATA(...) { __VA_ARGS__ }
#endif
#define RX_NAME_ARG(x) RX__ARG(name, x)
#define RX_VALUE_ARG(x) RX__ARG(value, x)
#define RX_RUN_ARG(x) RX__ARG(run, x)
static const struct rx__data foo
= RX__MAKE_DATA(RX_NAME_ARG("abc"), RX_VALUE_ARG(123), RX_RUN_ARG(run));
And it's all working great here again, except that the user now has to set the arguments using macros instead of the previous designated initializer syntax.
So the questions is: how can I keep track of these user-defined struct members while preserving the designated initializer syntax?
Note: if possible, I'd really like to have a robust way of detecting if a member was defined, so no in-band indicators—that is, no ”if this member has this magic value, then it's likely that is wasn't explicitely set”.
Just found my own answer, thanks rubber duck!
#include <stdio.h>
/* -------------------------------------------------------------------------- */
#define EXPAND(x) x
#define ARG_IDX(_1, _2, _3, _4, _5, _6, _7, _8, n, ...) n
#define COUNT_ARGS(...) EXPAND(ARG_IDX(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0))
#define CONCAT_0(a, b) a ## b
#define CONCAT(a, b) CONCAT_0(a, b)
#define APPLY_0(x)
#define APPLY_1(x, _1) \
x(_1)
#define APPLY_2(x, _1, _2) \
x(_1) x(_2)
#define APPLY_3(x, _1, _2, _3) \
x(_1) x(_2) x(_3)
#define APPLY_4(x, _1, _2, _3, _4) \
x(_1) x(_2) x(_3) x(_4)
#define APPLY_5(x, _1, _2, _3, _4, _5) \
x(_1) x(_2) x(_3) x(_4) x(_5)
#define APPLY_6(x, _1, _2, _3, _4, _5, _6) \
x(_1) x(_2) x(_3) x(_4) x(_5) x(_6)
#define APPLY_7(x, _1, _2, _3, _4, _5, _6, _7) \
x(_1) x(_2) x(_3) x(_4) x(_5) x(_6) x(_7)
#define APPLY_8(x, _1, _2, _3, _4, _5, _6, _7, _8) \
x(_1) x(_2) x(_3) x(_4) x(_5) x(_6) x(_7) x(_8)
#define APPLY(x, ...) EXPAND(x(__VA_ARGS__))
#define MAP(x, ...) \
EXPAND(APPLY(CONCAT(APPLY_, COUNT_ARGS(__VA_ARGS__)), x, __VA_ARGS__))
/* -------------------------------------------------------------------------- */
typedef int (*rx_run_fn)();
int run() { return 999; }
#ifdef __cplusplus
struct rx__data {
struct {
const char *name;
double number;
rx_run_fn run;
} value;
struct {
int name;
int number;
int run;
} defined;
};
#define RX__WRAP_ASSIGNMENT(x) out.value x; out.defined x ? 1 : 1;
#define RX__MAKE_DATA(...) \
[]() -> struct rx__data { \
struct rx__data out = {}; \
MAP(RX__WRAP_ASSIGNMENT, __VA_ARGS__); \
return out; \
}()
#define RX__GET_ARG_VALUE(data, field) data . value . field
#define RX__IS_ARG_DEFINED(data, field) data . defined . field
#else
struct rx__data {
const char *name;
int name_defined;
double number;
int number_defined;
rx_run_fn run;
int run_defined;
};
#define RX__WRAP_ASSIGNMENT(x) x, 1,
#define RX__MAKE_DATA(...) { MAP(RX__WRAP_ASSIGNMENT, __VA_ARGS__) }
#define RX__GET_ARG_VALUE(data, field) data . field
#define RX__IS_ARG_DEFINED(data, field) data . field##_defined
#endif
static const struct rx__data foo = RX__MAKE_DATA(
.name = "abc", .number = 1.23, .run = run);
int
main(void)
{
if (RX__IS_ARG_DEFINED(foo, name)) {
printf("name : %s\n", RX__GET_ARG_VALUE(foo, name));
} else {
printf("name : (not defined)\n");
}
if (RX__IS_ARG_DEFINED(foo, number)) {
printf("number : %f\n", RX__GET_ARG_VALUE(foo, number));
} else {
printf("number : (not defined)\n");
}
if (RX__IS_ARG_DEFINED(foo, run)) {
printf("run : %d\n", RX__GET_ARG_VALUE(foo, run)());
} else {
printf("run : (not defined)\n");
}
return 0;
}

Variadic macros with zero or more additional arguments

I have a macro for checking results of some test methods:
#define Eval(func, ...) if (func == -1) { printf(__VA_ARGS__); return -1; }
I want to get this functionally:
Eval(Check_1(),"Check1 failed."); // case 1
Eval(Check_2()); // case 2
Eval(Check_3(), "some variable=%i", variableValue); // case 3
At case 1 I want to write comment to user ("Check1 failed") and then return -1 (it's work).
At case 2 I just want to return from method, not print any information for user. So I must to detect situation of empty comment and not to call printf() - it's not work.
If any of "Check_x" methods failed, i need exit from current method by return code -1;
Is it any way to do this with macro?
Very similar question was here: Standard alternative to GCC's ##VA_ARGS trick? , but I can't modify this code for my situation.
EDIT:
I use C99 standart.
At current version of my code case 2 compiled with error "expected an expression" (I think it because of comma and empty argument).
Also I need to use case 3 for print additional information (variable values).
So, second argument not actually simple string.
EDIT2:
I get solution for my task. Here I find it
// Macro to count of arguments
#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 10,9,8,7,6,5,4,3,2,1)
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N
// Macro dispatcher
#define macro_dispatcher(func, ...) macro_dispatcher_(func, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(func, nargs) macro_dispatcher__(func, nargs)
#define macro_dispatcher__(func, nargs) func ## nargs
#define EVAL_UNIVERSAL(...) macro_dispatcher(EV, __VA_ARGS__)(__VA_ARGS__)
#define EV1(func) if (func == -1) return -1;
#define EV2(func, ...) if (func == -1) { printf(__VA_ARGS__); return -1; }
#define EV3(func, ...) EV2(func, __VA_ARGS__)
#define EV4(func, ...) EV2(func, __VA_ARGS__)
#define EV5(func, ...) EV2(func, __VA_ARGS__)
#define EV6(func, ...) EV2(func, __VA_ARGS__)
#define EV7(func, ...) EV2(func, __VA_ARGS__)
And I use it like this:
EVAL_UNIVERSAL(CheckInitialParameters());
EVAL_UNIVERSAL(CheckInitialParameters(), "text");
EVAL_UNIVERSAL(CheckInitialParameters(), "%i", 1);
EVAL_UNIVERSAL(CheckInitialParameters(), "%i %i", 1, 2);
Very thanks to Jens Gustedt, and rmn (http://efesx.com/)
// Macro to count of arguments
#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 10,9,8,7,6,5,4,3,2,1)
#define VA_NUM_ARGS_IMPL(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N
// Macro dispatcher
#define macro_dispatcher(func, ...) macro_dispatcher_(func, VA_NUM_ARGS(__VA_ARGS__))
#define macro_dispatcher_(func, nargs) macro_dispatcher__(func, nargs)
#define macro_dispatcher__(func, nargs) func ## nargs
#define EVAL_UNIVERSAL(...) macro_dispatcher(EV, __VA_ARGS__)(__VA_ARGS__)
#define EV1(func) if (func == -1) return -1;
#define EV2(func, ...) if (func == -1) { printf(__VA_ARGS__); return -1; }
#define EV3(func, ...) EV2(func, __VA_ARGS__)
#define EV4(func, ...) EV2(func, __VA_ARGS__)
#define EV5(func, ...) EV2(func, __VA_ARGS__)
#define EV6(func, ...) EV2(func, __VA_ARGS__)
#define EV7(func, ...) EV2(func, __VA_ARGS__)
And I use it like this:
EVAL_UNIVERSAL(CheckInitialParameters());
EVAL_UNIVERSAL(CheckInitialParameters(), "text");
EVAL_UNIVERSAL(CheckInitialParameters(), "%i", 1);
EVAL_UNIVERSAL(CheckInitialParameters(), "%i %i", 1, 2);

CUDA kernel launch macro with templates

I made a macro to simplify CUDA kernel calls:
#define LAUNCH LAUNCH_ASYNC
#define LAUNCH_ASYNC(kernel_name, gridsize, blocksize, ...) \
LOG("Async kernel launch: " #kernel_name); \
kernel_name <<< (gridsize), (blocksize) >>> (__VA_ARGS__);
#define LAUNCH_SYNC(kernel_name, gridsize, blocksize, ...) \
LOG("Sync kernel launch: " #kernel_name); \
kernel_name <<< (gridsize), (blocksize) >>> (__VA_ARGS__); \
cudaDeviceSynchronize(); \
// error check, etc...
Usage:
LAUNCH(my_kernel, 32, 32, param1, param2)
LAUNCH(my_kernel<int>, 32, 32, param1, param2)
This works fine; with the first define I can enable synronous calls and error checking for debugging.
However it does not work with multiple template arguments like below:
LAUNCH(my_kernel<int,float>, 32, 32, param1, param3)
The error message I get in the line where I call the macro:
error : expected a ">"
Is it possible to make this macro work with multiple template arguments?
The problem is that the preprocessor knows nothing about angle bracket nesting, so it interprets the comma between them as macro argument separator.
If the kernel-launch syntax supports parentheses around the kernel name (I can't check now, not on a CUDA machine), you could do this:
LAUNCH((my_kernel<int, float>), 32, 32, param1, param3)
Something else you could try that I have used (based on the macro you posted) is wrapping the kernel block size and grid size arguments in their own macro:
#define KERNEL_ARGS2(grid, block) <<< grid, block >>>
#define KERNEL_ARGS3(grid, block, sh_mem) <<< grid, block, sh_mem >>>
#define KERNEL_ARGS4(grid, block, sh_mem, stream) <<< grid, block, sh_mem, stream >>>
Now you should be able to use your macro like so:
#define CUDA_LAUNCH(kernel_name, gridsize, blocksize, ...) \
kernel_name KERNEL_ARGS2(gridsize, blocksize)(__VA_ARGS__);
You can use it like:
CUDA_LAUNCH(my_kernel, grid_size, block_size, float* input, float* output, int size);
This will launch the kernel called 'my_kernal' with the given grid and block size and the input arguments.
consider this solution that also throws error
inline void echoError(cudaError_t e, const char *strs) {
char a[255];
if (e != cudaSuccess) {
strncpy(a, strs, 255);
fprintf(stderr, "Failed to %s,errorCode %s",
a, cudaGetErrorString(e));
exit(EXIT_FAILURE);
}
}
#define CUDA_KERNEL_DYN(kernel, bpg, tpb, shd, ...){ \
kernel<<<bpg,tpb,shd>>>( __VA_ARGS__ ); \
cudaError_t err = cudaGetLastError(); \
echoError(err, #kernel); \
}

C/C++ How to expand a macro parameter into text between quotes

Here is what I have (message() is a specialized logging function from a third party library):
#define LOG(fmt, ...) message("%s %s(): #fmt", __FILE__, __func__, __VA_ARGS__);
So I want to be able to do things like:
LOG("Hello world")
LOG("Count = %d", count)
And have it expand to:
message("%s %s(): Hello world", __FILE__, __func__);
message("%s %s(): Count = %d", __FILE__, __func__, count);
But the #fmt thing is not working. It does not evaluate to the macro argument and prints as "#fmt". Is it possible to do what I'm trying to do?
Don't put #fmt in the quotes. Just use string literal concatenation to join the two literals.
#define LOG(fmt, ...) message("%s %s(): " fmt, __FILE__, __func__, __VA_ARGS__);