2016-02-23 27 views
8

我想用C11_Generic关键字根据静态类型,以填补工会,如:_Generic填补一些工会

typedef union { 
    double d; 
    long l; 
    const char*s; 
    void*p; 
} ty; 

#define make_ty(X) _Generic((X),      \ 
          double: (ty){.d=(X)},  \ 
          long: (ty){.l=(X)},   \ 
          const char*: (ty){.s=(X)}, \ 
          default: (ty){.p=(X)}) 

ty from_double(double x) { return make_ty(x); } 
ty from_string(const char*s) { return make_ty(s); } 
ty from_long(long l) { return make_ty(l);} 

但是这并不编译,例如GCC 5.3给出了(与gcc -std=c11 -Wall):

u.c: In function ‘from_double’: 
u.c:11:35: error: incompatible types when initializing type ‘const char *’ 
        using type ‘double’ 
       const char*: (ty){.s=(X)}, \ 
           ^
u.c:14:41: note: in expansion of macro ‘make_ty’ 
     ty from_double(double x) { return make_ty(x); } 

BTW,使用gcc -std=c99 -Wall给出了同样的错误...

还是_Generic唯一有用tgmath.h

我认为_Generic根据编译器已知类型选择表达,所以无意义的(ty){.s=(x)}将在from_double ....

被忽略(如果没有工作,我将能够“超载” make_ty根据静态,编译器知道,类型参数的...)

+1

好吧,但即使在'-std = c11'这不起作用 –

+1

[This question](http://stackoverflow.com/questions/24743520/incompatible-pointer-types-passing-in-generic-macro)有一个类似的问题,最好的答案可能会回答你的问题 –

+0

关于同一主题的其他答案似乎表明,其他案件不允许包含*违反约束*(错误类型的初始化确实是其中之一) –

回答

5

_Generic各分支机构必须是有效的代码,丝毫不亚于在类似if (1) { here; } else { there; }。要有一个解决方案,你可以采取相反的方式。定义类似的功能:

inline ty from_double(double x) { return (ty){ .d = x }; } 

您所有的情况下,然后让宏为:

#define make_ty(X) _Generic((X),      \ 
          double: from_double,  \ 
          double: from_long,  \ 
          ...)(X) 

随着通过inline编译器的知名度实际上能够优化这样的代码,并且通常无法通过调用函数指针。