How to define a macro function returns void or else in C ++


I have defined the following two function macros to check the exit flag in my thread class.

//use this in run()
#define CHECK_EXIT  if( exitFlag_ ) {\
    //do something\
    return;\
}\

//use this in function
#define CHECK_EXIT_IN_FUNC  if( exitFlag_ ) {\
    //do something\
    return false;\
}\

      

I had to define them separately because the return value is different.
Can I define it in one macro?
I googled but couldn't find an answer.
Thanks for any advice.

+3


source to share


3 answers


You can use a variable macro. Don't skip anything if you don't want to return anything after verification.

#define CHECK_EXIT(...) CHECK_EXIT_(_, ##__VA_ARGS__)
#define CHECK_EXIT_(...) CHECK_EXIT_X(__VA_ARGS__, _1, _0)(__VA_ARGS__)
#define CHECK_EXIT_X(_0, _1, X, ...) CHECK_EXIT ## X
#define CHECK_EXIT_0(_) do if (exit_flag_) { /*...*/ return; } while(0)
#define CHECK_EXIT_1(_, R) do if (exit_flag_) { /*...*/ return (R); } while(0)

void test_0 () {
    bool exit_flag_ = true;
    CHECK_EXIT();
}

int test_1 () {
    bool exit_flag_ = true;
    CHECK_EXIT(0);
    return 1;
}

      



I used a very simplified version of the argument counting argument described in another answer . I can simplify it because I rely on the GCC ( ##__VA_ARGS__

) extension to remove the trailing comma if the variable argument expansion is empty. Use the full version unless you are using a compiler that understands this GCC extension.

+4


source


C ++ 11's rules for return types create a slightly interesting case:

A return statement with a non-void expression can only be used in functions that return a value; the value of the expression is returned to the calling function. The value of an expression is implicitly converted to the return type of the function in which it appears.

and later

The return statement with a type expression void

can only be used in functions with a return type cv

void

; the expression is evaluated just before the function returns to the caller.

It seemed natural to create a type that is implicitly convertible to void

. Unfortunately, the expression is of this custom type, which is considered a non-empty type and is rejected.



struct does_not_work
{
    operator void() const {}
    template<typename T> operator T() const { return T{}; }
};

      

I'm not sure if I would support rewriting the rule to allow types that are implicitly convertible to a return type, even if that return type is invalid.

Likewise, this deviates:

return {};

      

(but the same void{}

)

+3


source


I'm not sure how you can do this "in the same macro" for different types of functions unless you specify the actual return value from the outside.

If you don't mind this, then you can take advantage of the fact that in C ++ (but not C) you can return invalid expressions from void functions. For example, you can return (void) 0

"void" as a value. That is, you can do

#define CHECK_EXIT_IN_FUNC(ret)  if( exitFlag_ ) {\
    //do something\
    return (ret);\
}

      

and call it as CHECK_EXIT_IN_FUNC(false)

or CHECK_EXIT_IN_FUNC((void) 0)

depending on the type of the function.

+2


source







All Articles