简体   繁体   中英

Does each branch of c11 _Generic generic association's result expressions have to be valid?

I can't seem to pass the arguments to functions expecting different arguments (or to other _Generic macros which implement a subset of the types of the first one).

#define DEBUG_PRINT(x,...) _Generic((x),                    \
    debug_print_options *: DEBUG_PRINT_CUSTOM_TYPE(x,  __VA_ARGS__),    \
    default: DEBUG_PRINT_BASIC_TYPE(x, __VA_ARGS__))


#define DEBUG_PRINT_BASIC_TYPE(x,...) debug_print_printf_specifier((#x), (x), TYPE_TO_PRINTF_SPECIFIER(x), __FILE__, __LINE__, _my_func__, &((struct debug_print_options){__VA_ARGS__}))
#define DEBUG_PRINT_CUSTOM_TYPE(x,...) debug_print_custom_to_debug_string((#x), (x), GET_CREATE_DEBUG_STRING_FUNC(x), __FILE__, __LINE__, _my_func__, &((struct debug_print_options){__VA_ARGS__}))

gives a compile error:

debug_print.h:123:46: error: ‘_Generic’ selector of type ‘struct debug_print_options *’ is not compatible with any association

which makes it seem like it's getting evaluated at every branch. If I comment out the default it compiles.

Is there a way to work around this?

Your compiler error is not comming from the macros themselves, but from some invocation of them. So, it would help if you posted the invocation that is causing the error. That being said, I will address what seem to be your general questions on _Generic expressions.

The standard says the following (6.5.1.1, under 'semantics'):

The controlling expression of a generic selection is not evaluated. If a generic selection has a generic association with a type name that is compatible with the type of the controlling expression, then the result expression of the generic selection is the expression in that generic association. Otherwise, the result expression of the generic selection is the expression in the default generic association. None of the expressions from any other generic association of the generic selection is evaluated.

So, in answer to your comment add on to your question, no, only the selected branch is evaluated.

_Generic expressions are expressions, not macros. A macro does not need to have proper syntax. It does not even need to be parenthetically balanced. The only think a macro needs to do is expand into valid code each time it is used. Expressions are different. They need to match the syntax of the language.

In the case of a _Generic expression, the syntax of each item can be any valid C expression that does not have a comma operator that is not parenthetically (or conditional operator) shielded. If your _Generic meets this criteria, and the selected statement does not cause a problem, then it will work. So, as long as the syntax is valid, it will work.

Having proper syntax when you don't know the type of your variable can be a little tricky. If you are having trouble with that, you can insert explicit casts on 'x' where needed, casting it to the type it would be on that branch. This way the code is valid, and the casts are redundant and will be optimized out.

As for the particular error you got, it sounds like the error you'd get if you did not have a type that matched your input and you had no default statement. Again, without seeing your invocation, it is hard to say. But I'd make sure you are matching the type exactly including qualifiers. One particular question I'd ask is if debug_print_options is a typedef, as if it is only defined as a structure tag then you need to put 'struct' in your _Generic to correctly identify the type.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM