Re:A Better Varargs
by cfallin on Wednesday February 10, 2016 @07:54PM
(#11077490)
In principle, it seems you could handle the heterogenous case by designing an `Any` struct and (at least in C++) implicit constructors to take various types (int, T*, ...). At some point this starts to feel like designing a custom ABI and the complexity may not be worth it, but it seems there should be a way :-)
[ Parent
| on HN ]
> it seems you could handle the heterogenous case by designing an `Any` struct and (at least in C++) implicit constructors to take various types (int, T*, ...)
In C11 you could also use _Generic. It will be perfect for the year 2045 when Microsoft adds C11 support.
Re:A Better Varargs
by ryanprichard on Thursday February 11, 2016 @01:17AM
(#11078525)
_Generic might not work so well to handle int vs double vs pointer-to-T. Apparently, even unselected associations must type-check.
e.g.: Here's a simple implementation:
enum AnyKind { AnyInt, AnyDouble, AnyStr };
struct Any {
enum AnyKind kind;
union {
int i;
double d;
const char *s;
} u;
};
#define ANY(x) \
_Generic((x), \
int: (struct Any){ .kind = AnyInt, .u.i = (x) }, \
double: (struct Any){ .kind = AnyDouble, .u.d = (x) }, \
const char *: (struct Any){ .kind = AnyStr, .u.s = (x) })
int main() {
ANY(1);
ANY(1.0);
ANY("abc");
}
Clang gives errors like: error: initializing 'const char *' with an expression of incompatible type 'double'
This issue was discussed a bit on the GCC bugtracker: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64509Qualifiers might also be an issue. My impression so far is that every combination of differently qualified type is supposed to require a different _Generic association. (GCC 5.2 and Clang 3.7 differ here.) That would require a huge number of _Generic associations, but it might be possible to strip the qualifiers using a comma operator, _Generic( (0,(x)), ... ). A comma expression is not an lvalue, so perhaps it cannot be qualified. DR423[1] askes that question.
[1] http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_423.htm