Date: Tue, 10 Mar 2020 20:16:21 +0100
* Jens Gustedt via Liaison:
> The second is, that generic selection is a very nice tool to implement
> traits and similar things. Just as an example from the reference
> implementation that I am trying to build currently and that
> simultaneously generates generic selections for C and overloaded
> functions for C++:
>
> #define tohighest(X) _Generic((X), \
> signed char: (signed char)(((unsigned char)-1)/2),\
> signed short: (signed short)(((unsigned short)-1)/2),\
> signed int: (signed int)(((unsigned int)-1)/2),\
> signed long: (signed long)(((unsigned long)-1)/2),\
> signed long long: (signed long long)(((unsigned long long)-1)/2),\
> char: (char)(((unsigned char)-1)/(((char)-1 > 0) ? 1 : 2)),\
> float: HUGE_VALF,\
> double: HUGE_VAL,\
> long double: HUGE_VALL,\
> default: (generic_type(X))(((generic_type(X))-1)/(((generic_type(X))-1) < 0 ? 2 : 1)))
>
> (the real code I have for this is even shorter, but that's another story)
>
> Basically what the user has to write here is one line per type, which
> is very concise and fits on one screen with a "tabular" layout (type
> left, expression right). For C++ the generated code is 9 overloaded
> functions and a template for the default case. This boiler plate
> introduces a lot of possibilities for mistakes.
That may be so, but you simply cannot use these lists in cases where
any macro parameter is expanded more than once. Even for the default
case in your example, you probably would have to use some lambda
construct to capture the type of X, or you risk running into the same
macro explosion issue we encountered with the original <tgmath.h>
implementation in glibc.
Do you think there is a mechanical way to capture types and values so
that each macro argument is expanded exactly once? Perhaps using
lambdas?
> The second is, that generic selection is a very nice tool to implement
> traits and similar things. Just as an example from the reference
> implementation that I am trying to build currently and that
> simultaneously generates generic selections for C and overloaded
> functions for C++:
>
> #define tohighest(X) _Generic((X), \
> signed char: (signed char)(((unsigned char)-1)/2),\
> signed short: (signed short)(((unsigned short)-1)/2),\
> signed int: (signed int)(((unsigned int)-1)/2),\
> signed long: (signed long)(((unsigned long)-1)/2),\
> signed long long: (signed long long)(((unsigned long long)-1)/2),\
> char: (char)(((unsigned char)-1)/(((char)-1 > 0) ? 1 : 2)),\
> float: HUGE_VALF,\
> double: HUGE_VAL,\
> long double: HUGE_VALL,\
> default: (generic_type(X))(((generic_type(X))-1)/(((generic_type(X))-1) < 0 ? 2 : 1)))
>
> (the real code I have for this is even shorter, but that's another story)
>
> Basically what the user has to write here is one line per type, which
> is very concise and fits on one screen with a "tabular" layout (type
> left, expression right). For C++ the generated code is 9 overloaded
> functions and a template for the default case. This boiler plate
> introduces a lot of possibilities for mistakes.
That may be so, but you simply cannot use these lists in cases where
any macro parameter is expanded more than once. Even for the default
case in your example, you probably would have to use some lambda
construct to capture the type of X, or you risk running into the same
macro explosion issue we encountered with the original <tgmath.h>
implementation in glibc.
Do you think there is a mechanical way to capture types and values so
that each macro argument is expanded exactly once? Perhaps using
lambdas?
Received on 2020-03-10 14:20:43