4 ms·
This works when the arguments are all the same type. But what if you wanted to implement, e.g. printf with this?
by AndyKelley 11y ago
This works when the arguments are all the same type. But what if you wanted to implement, e.g. printf with this?
- cfallin 11y agoIn 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 :-)
- haberman 11y ago> 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.
- ryanprichard 11y ago_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=64509 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64509 Qualifiers 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 http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_423.htm
- haberman 11y agoWhat a fantastically informative reply, thanks for this! Having not used _Generic myself, it's good to know what kind of limitations to expect.
- ksherlock 11y agoIf 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.