Search code examples
c++preprocessorvariadic

Achieve the opposite of __VA_OPT__ in variadic preprocessor function-like macros


How can I achieve the opposite effect of VA_OPT(), expanding only, if there are no variadic arguments in VA_ARGS. Something like VA_NOT_OPT().

Example:

#define MY_MACRO(...) __VA_NOT_OPT__(default) __VA_ARGS__

MY_MACRO() expands to default

MY_MACRO(arg) expands to arg

What I really want is a single optional parameter with a default value. But I think the C-Preprocessor doesn't support this. But maybe someone knows better than me.


Solution

  • You can build a little conditional expansion macro pretty easily, so that VALUE_IFNOT(1, args) expands to nothing and VALUE_IF(0, args) (or in this case VALUE_IF(, args) too) expands to args:

    #define VALUE_IFNOT_TEST(...) __VA_ARGS__
    #define VALUE_IFNOT_TEST0(...) __VA_ARGS__
    #define VALUE_IFNOT_TEST1(...)
    #define VALUE_IFNOT(COND, ...) VALUE_IFNOT_TEST ## COND ( __VA_ARGS__ )
    

    Then your "opposite of __VA_OPT__" macro looks like VALUE_IF(__VA_OPT__(1), value). This will expand to VALUE_IF(1, value) and nothing if there were variadic arguments and VALUE_IF(, value) and value if there weren't.

    For example https://godbolt.org/z/Kbc5jxEKf

    #define TEST(...) VALUE_IFNOT(__VA_OPT__(1), std::printf("Test expanded on line %d with args '%s'\n", __LINE__, #__VA_ARGS__); )
    
    int main() {
        TEST()      // TEST expanded on line 12 with args ''
        TEST(1)     // (no output)
        TEST(1, 2)  // (no output)
    }