Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

This works when the arguments are all the same type. But what if you wanted to implement, e.g. printf with this?


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.


_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

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


What a fantastically informative reply, thanks for this! Having not used _Generic myself, it's good to know what kind of limitations to expect.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: