cvariadic-macros

How do i add a secondary __VA_ARGS__?


I would like it so that the function (func parameter) can also take Variable args

#define TRY_IT(func, ret, bad_ret_code, give_up_call, ...)      \
    if((ret) == (bad_ret_code)) {                               \
        for(size_t i = 0; i <= TRY_IT_MAX_RETRIES; i++) {       \
            (ret) = (func)();                                   \
            if((ret != (bad_ret_code)))                         \
                break;                                          \
        }                                                       \
        if(ret == (bad_ret_code))                               \
            (give_up_call)(__VA_ARGS__)                         \
    }                                                           \

Solution

  • Use parentheses.

    Here is a variation on Eric Postpischil’s excellent (and simpler/superior) answer.

    You can use a simple preprocessor trick to remove parentheses.

    #define DEPAREN(X) DEPAREN_ X
    #define DEPAREN_(...) __VA_ARGS__
    

    Variations on this trick abound, depending on what you need it for. Now you can use your macro:

    #define TRY_IT(func, args, ret, bad_ret_code, give_up_call, ...) \
        if((ret) == (bad_ret_code)) {                                \
            for(size_t i = 0; i <= TRY_IT_MAX_RETRIES; i++) {        \
                (ret) = (func)(DEPAREN(args));                       \
                if((ret != (bad_ret_code)))                          \
                    break;                                           \
            }                                                        \
            if(ret == (bad_ret_code))                                \
                (give_up_call)(__VA_ARGS__)                          \
        }                                                            \
    

    This is useful if your function takes additional arguments that are not supplied as part of the macro replacement, such as:

                (ret) = (func)(7,"seven",DEPAREN(args));             \
    

    I believe you need C99 or better for empty argument lists to work properly, but I could be wrong about the version number. (Someone will correct me in comment if I am, but he or she could simply edit my post and that would be fine.)