top | item 11078525

(no title)

ryanprichard | 10 years 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

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

discuss

order

haberman|10 years ago

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