Re:A Better Varargs
by AndyKelley on Wednesday February 10, 2016 @07:21PM
(#11077334)
This works when the arguments are all the same type. But what if you wanted to implement, e.g. printf with this?
[ Parent
| on HN ]
If you go back to the genesis stack overflow question, the point is to make sure all the variadic arguments are of the same type. No, it wouldn't work for printf but gcc and clang have __attribute__(format) for that.
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 :-)
> 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