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

喜你入骨 提交于 2019-12-31 03:24:30

问题


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?


回答1:


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.



来源:https://stackoverflow.com/questions/29161049/does-each-branch-of-c11-generic-generic-associations-result-expressions-have-t

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!