_Generic 来填充一些 union
_Generic to fill some union
我想用C11 _Generic
关键字根据静态类型填充一个union,如:
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); }
顺便说一句,使用 gcc -std=c99 -Wall
给出了同样的错误...
或者 _Generic
只对 tgmath.h
有用吗?
我认为 _Generic
根据编译器已知的类型选择表达式,因此在 from_double
中将忽略无意义的 (ty){.s=(x)}
...
(如果确实有效,我将能够 "overload" make_ty
根据静态的、编译器已知的参数类型...)
_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
的可见性,编译器实际上能够优化此类代码,并且通常不会通过调用函数指针。
我想用C11 _Generic
关键字根据静态类型填充一个union,如:
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); }
顺便说一句,使用 gcc -std=c99 -Wall
给出了同样的错误...
或者 _Generic
只对 tgmath.h
有用吗?
我认为 _Generic
根据编译器已知的类型选择表达式,因此在 from_double
中将忽略无意义的 (ty){.s=(x)}
...
(如果确实有效,我将能够 "overload" make_ty
根据静态的、编译器已知的参数类型...)
_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
的可见性,编译器实际上能够优化此类代码,并且通常不会通过调用函数指针。