In C (not C++/C#) how do I check if a variable is of a certain type?
在C(不是c++ / c#)中,我如何检查变量是否为某种类型?
For example, something like this:
例如:
double doubleVar;
if( typeof(doubleVar) == double ) {
printf("doubleVar is of type double!");
}
Or more general: How do I compare two types so that compare(double1,double2)
will evaluate to true, and compare(int,double)
will evaluate to false. Also I'd like to compare structs of different composition as well.
或者更一般的:我如何比较两种类型,以便比较(double1,double2)将值为true,而比较(int,double)将值为false。我也想比较不同组成的结构。
Basically, I have a function that operates on variables of type "struct a" and "struct b". I want to do one thing with the "struct a" variables and the other with the "struct b" variables. Since C doesn't support overloading and the void
pointer losses its type information I need to check for type. BTW, what would be the sense in having a typeof
operator, if you can't compare types?
基本上,我有一个函数作用于"struct a"和"struct b"的变量。我想对"struct a"变量和"struct b"变量做一件事。由于C不支持重载,空指针丢失了它的类型信息,所以我需要检查类型。顺便说一句,如果您不能比较类型,那么拥有类型运算符的意义是什么呢?
The sizeof method seems to be a practical workaround solution for me. Thanks for your help. I still find it a bit strange since the types are known at compile time, but if I imagine the processes in the machine I can see, why the information is not stored in terms of types, but rather in terms of byte size. Size is the only thing really relevant besides addresses.
对于我来说,sizeof方法似乎是一个实用的解决方案。谢谢你的帮助。我仍然觉得这有点奇怪,因为这些类型在编译时是已知的,但是如果我想象一下我能看到的机器中的过程,为什么信息不是以类型的形式存储,而是以字节大小为单位。除了地址,大小是唯一真正相关的东西。
10 个解决方案
#1
26
Getting the type of a variable is, as of now, possible in C11 with the _Generic
generic selection. It works at compile-time.
到目前为止,通过_Generic selection在C11中获取变量的类型是可能的。它在编译时工作。
The syntaxis is a bit like switch
. Here's a sample (from this answer):
这种同步有点像开关。这是一个样本(来自这个答案):
#define typename(x) _Generic((x), \
_Bool: "_Bool", unsigned char: "unsigned char", \
char: "char", signed char: "signed char", \
short int: "short int", unsigned short int: "unsigned short int", \
int: "int", unsigned int: "unsigned int", \
long int: "long int", unsigned long int: "unsigned long int", \
long long int: "long long int", unsigned long long int: "unsigned long long int", \
float: "float", double: "double", \
long double: "long double", char *: "pointer to char", \
void *: "pointer to void", int *: "pointer to int", \
default: "other")
To actually use it for compile-time manual type checking, you can define an enum
with all of the types you expect, something like this:
要实际使用它进行编译时手动类型检查,您可以定义一个枚举,其中包含您期望的所有类型,如下所示:
enum t_typename {
TYPENAME_BOOL,
TYPENAME_UNSIGNED_CHAR,
TYPENAME_CHAR,
TYPENAME_SIGNED_CHAR,
TYPENAME_SHORT_INT,
TYPENAME_UNSIGNED_CHORT_INT,
TYPENAME_INT,
/* ... */
TYPENAME_POINTER_TO_INT,
TYPENAME_OTHER
};
And then use _Generic
to match types to this enum
:
然后使用_Generic将类型匹配到此枚举:
#define typename(x) _Generic((x), \
_Bool: TYPENAME_BOOL, unsigned char: TYPENAME_UNSIGNED_CHAR, \
char: TYPENAME_CHAR, signed char: TYPENAME_SIGNED_CHAR, \
short int: TYPENAME_SHORT_INT, unsigned short int: TYPENAME_UNSIGNED_SHORT_INT, \
int: TYPENAME_INT, \
/* ... */ \
int *: TYPENAME_POINTER_TO_INT, \
default: TYPENAME_OTHER)
#2
13
C does not support this form of type introspection. What you are asking is not possible in C (at least without compiler-specific extensions; it would be possible in C++, however).
C不支持这种形式的类型内省。您所要求的在C语言中是不可能的(至少没有特定于编译器的扩展;但是,在c++中是可能的)。
In general, with C you're expected to know the types of your variable. Since every function has concrete types for its parameters (except for varargs, I suppose), you don't need to check in the function body. The only remaining case I can see is in a macro body, and, well, C macros aren't really all that powerful.
一般来说,用C你应该知道变量的类型。由于每个函数都有其参数的具体类型(我想,除了varargs),所以不需要检查函数体。我能看到的唯一的情况是在宏体中,而且,C宏并不是那么强大。
Further, note that C does not retain any type information into runtime. This means that, even if, hypothetically, there was a type comparison extension, it would only work properly when the types are known at compile time (ie, it wouldn't work to test whether two void *
point to the same type of data).
此外,请注意,C不会在运行时中保留任何类型信息。这意味着,即使假设存在类型比较扩展,它也只能在编译时知道类型时才能正常工作(例如,测试两个void *是否指向相同类型的数据)。
As for typeof
: First, typeof
is a GCC extension. It is not a standard part of C. It's typically used to write macros that only evaluate their arguments once, eg (from the GCC manual):
至于typeof:首先,typeof是GCC扩展。它不是c的标准部分,它通常用于编写只计算一次参数的宏,例如(来自GCC手册):
#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
The typeof
keyword lets the macro define a local temporary to save the values of its arguments, allowing them to be evaluated only once.
typeof关键字允许宏定义本地临时,以保存其参数的值,允许只计算一次。
In short, C does not support overloading; you'll just have to make a func_a(struct a *)
and func_b(struct b *)
, and call the correct one. Alternately, you could make your own introspection system:
简而言之,C不支持超载;您只需创建一个func_a(struct a *)和func_b(struct b *)并调用正确的。或者,你可以建立自己的自省系统:
struct my_header {
int type;
};
#define TYPE_A 0
#define TYPE_B 1
struct a {
struct my_header header;
/* ... */
};
struct b {
struct my_header header;
/* ... */
};
void func_a(struct a *p);
void func_b(struct b *p);
void func_switch(struct my_header *head);
#define func(p) func_switch( &(p)->header )
void func_switch(struct my_header *head) {
switch (head->type) {
case TYPE_A: func_a((struct a *)head); break;
case TYPE_B: func_b((struct b *)head); break;
default: assert( ("UNREACHABLE", 0) );
}
}
You must, of course, remember to initialize the header properly when creating these objects.
当然,您必须记住在创建这些对象时正确初始化头部。
#3
9
As other people have already said this isn't supported in the C language. You could however check the size of a variable using the sizeof()
function. This may help you determine if two variables can store the same type of data.
正如其他人已经说过的,这在C语言中不受支持。但是,您可以使用sizeof()函数检查变量的大小。这可以帮助您确定两个变量是否可以存储相同类型的数据。
Before you do that, read the comments below.
在此之前,请阅读下面的评论。
#4
5
As others have mentioned, you can't extract the type of a variable at runtime. However, you could construct your own "object" and store the type along with it. Then you would be able to check it at runtime:
正如其他人提到的,您不能在运行时提取变量的类型。但是,您可以构建自己的“对象”并将类型连同它一起存储。然后你可以在运行时检查:
typedef struct {
int type; // or this could be an enumeration
union {
double d;
int i;
} u;
} CheesyObject;
Then set the type as needed in the code:
然后根据代码的需要设置类型:
CheesyObject o;
o.type = 1; // or better as some define, enum value...
o.u.d = 3.14159;
#5
4
Gnu GCC has a builtin function for comparing types __builtin_types_compatible_p
.
Gnu GCC有一个内置函数,用于比较__builtin_types_compatible_p类型。
https://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Other-Builtins.html
https://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Other-Builtins.html
This built-in function returns 1 if the unqualified versions of the types type1 and type2 (which are types, not expressions) are compatible, 0 otherwise. The result of this built-in function can be used in integer constant expressions.
如果type1和type2类型的非限定版本(类型是类型,而不是表达式)兼容,则此内置函数返回1,否则返回0。这个内置函数的结果可以用于整数常量表达式。
This built-in function ignores top level qualifiers (e.g., const, volatile). For example, int is equivalent to const int.
这个内置函数忽略*限定符(例如const、volatile)。例如,int相当于const int。
Used in your example:
中使用的例子:
double doubleVar;
if(__builtin_types_compatible_p(typeof(doubleVar), double)) {
printf("doubleVar is of type double!");
}
#6
2
This is crazily stupid, but if you use the code:
这太愚蠢了,但是如果你使用代码:
fprintf("%x", variable)
and you use the -Wall flag while compiling, then gcc will kick out a warning of that it expects an argument of 'unsigned int' while the argument is of type '____'. (If this warning doesn't appear, then your variable is of type 'unsigned int'.)
当编译时使用-Wall标志时,gcc就会发出警告,它期望参数为'unsigned int',而参数为'____'。(如果没有出现此警告,则您的变量类型为'unsigned int'。)
Best of luck!
最好的运气!
Edit: As was brought up below, this only applies to compile time. Very helpful when trying to figure out why your pointers aren't behaving, but not very useful if needed during run time.
编辑:如下所示,这只适用于编译时间。在试图弄清楚指针为什么不正常时非常有用,但是如果在运行时需要的话就不是很有用。
#7
1
From linux/typecheck.h:
从linux / typecheck.h:
/*
* Check at compile time that something is of a particular type.
* Always evaluates to 1 so you may use it easily in comparisons.
*/
#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})
Here you can find explanation which statements from standard and which GNU extensions above code uses.
在这里,您可以找到来自标准的声明和以上代码使用的GNU扩展。
(Maybe a bit not in scope of the question, since question is not about failure on type mismatch, but anyway, leaving it here).
(可能不是在问题的范围内,因为问题不是关于类型不匹配的失败,而是不管怎样,把它留在这里)。
#8
0
C is statically typed language. You can't declare a function which operate on type A or type B, and you can't declare variable which hold type A or type B. Every variable has an explicitly declared and unchangeable type, and you supposed to use this knowledge.
C是静态类型语言。你不能声明一个作用于类型a或类型B的函数,也不能声明保存类型a或类型B的变量。
And when you want to know if void * points to memory representation of float or integer - you have to store this information somewhere else. The language is specifically designed not to care if char * points to something stored as int or char.
当你想知道void *是否指向浮点或整数的内存表示时,你必须将这些信息存储在其他地方。该语言是专门设计的,不关心char *指向存储为int或char的东西。
#9
0
For that purpose I have written a simple C program for that... It is in github...GitHub Link
为此,我编写了一个简单的C程序……在github……GitHub链接
Here how it works... First convert your double into a char string named s..
在这里它是如何工作的…首先将您的double转换成一个名为s的char字符串。
char s[50];
sprintf(s,"%.2f", yo);
Then use my dtype
function to determine the type... My function will return a single character...You can use it like this...
然后使用我的dtype函数来确定类型…我的函数将返回一个字符……你可以这样使用它……
char type=dtype(s);
//Return types are :
//i for integer
//f for float or decimals
//c for character...
Then you can use comparison to check it... That's it...
然后你可以用比较来检查……就是这样……
#10
0
As another answer mentioned, you can now do this in C11 with _Generic
.
正如前面提到的另一个答案,您现在可以在C11中使用_Generic实现这一点。
For example, here's a macro that will check if some input is compatible with another type:
例如,这里有一个宏,用于检查某些输入是否与另一种类型兼容:
#include <stdbool.h>
#define isCompatible(x, type) _Generic(x, type: true, default: false)
You can use the macro like so:
你可以这样使用宏:
double doubleVar;
if (isCompatible(doubleVar, double)) {
printf("doubleVar is of type double!\n"); // prints
}
int intVar;
if (isCompatible(intVar, double)) {
printf("intVar is compatible with double too!\n"); // doesn't print
}
This can also be used on other types, including structs. E.g.
这也可以用于其他类型,包括struct。如。
struct A {
int x;
int y;
};
struct B {
double a;
double b;
};
int main(void)
{
struct A AVar = {4, 2};
struct B BVar = {4.2, 5.6};
if (isCompatible(AVar, struct A)) {
printf("Works on user-defined types!\n"); // prints
}
if (isCompatible(BVar, struct A)) {
printf("And can differentiate between them too!\n"); // doesn't print
}
return 0;
}
And on typedefs.
类型定义。
typedef char* string;
string greeting = "Hello world!";
if (isCompatible(greeting, string)) {
printf("Can check typedefs.\n");
}
However, it doesn't always give you the answer you expect. For instance, it can't distinguish between an array and a pointer.
然而,它并不总是给出你所期望的答案。例如,它不能区分数组和指针。
int intArray[] = {4, -9, 42, 3};
if (isCompatible(intArray, int*)) {
printf("Treats arrays like pointers.\n");
}
// The code below doesn't print, even though you'd think it would
if (isCompatible(intArray, int[4])) {
printf("But at least this works.\n");
}
Answer borrowed from here: http://www.robertgamble.net/2012/01/c11-generic-selections.html
答案从这里借用:http://www.robertgamble.net/2012/01/c11-generic selections.html。
#1
26
Getting the type of a variable is, as of now, possible in C11 with the _Generic
generic selection. It works at compile-time.
到目前为止,通过_Generic selection在C11中获取变量的类型是可能的。它在编译时工作。
The syntaxis is a bit like switch
. Here's a sample (from this answer):
这种同步有点像开关。这是一个样本(来自这个答案):
#define typename(x) _Generic((x), \
_Bool: "_Bool", unsigned char: "unsigned char", \
char: "char", signed char: "signed char", \
short int: "short int", unsigned short int: "unsigned short int", \
int: "int", unsigned int: "unsigned int", \
long int: "long int", unsigned long int: "unsigned long int", \
long long int: "long long int", unsigned long long int: "unsigned long long int", \
float: "float", double: "double", \
long double: "long double", char *: "pointer to char", \
void *: "pointer to void", int *: "pointer to int", \
default: "other")
To actually use it for compile-time manual type checking, you can define an enum
with all of the types you expect, something like this:
要实际使用它进行编译时手动类型检查,您可以定义一个枚举,其中包含您期望的所有类型,如下所示:
enum t_typename {
TYPENAME_BOOL,
TYPENAME_UNSIGNED_CHAR,
TYPENAME_CHAR,
TYPENAME_SIGNED_CHAR,
TYPENAME_SHORT_INT,
TYPENAME_UNSIGNED_CHORT_INT,
TYPENAME_INT,
/* ... */
TYPENAME_POINTER_TO_INT,
TYPENAME_OTHER
};
And then use _Generic
to match types to this enum
:
然后使用_Generic将类型匹配到此枚举:
#define typename(x) _Generic((x), \
_Bool: TYPENAME_BOOL, unsigned char: TYPENAME_UNSIGNED_CHAR, \
char: TYPENAME_CHAR, signed char: TYPENAME_SIGNED_CHAR, \
short int: TYPENAME_SHORT_INT, unsigned short int: TYPENAME_UNSIGNED_SHORT_INT, \
int: TYPENAME_INT, \
/* ... */ \
int *: TYPENAME_POINTER_TO_INT, \
default: TYPENAME_OTHER)
#2
13
C does not support this form of type introspection. What you are asking is not possible in C (at least without compiler-specific extensions; it would be possible in C++, however).
C不支持这种形式的类型内省。您所要求的在C语言中是不可能的(至少没有特定于编译器的扩展;但是,在c++中是可能的)。
In general, with C you're expected to know the types of your variable. Since every function has concrete types for its parameters (except for varargs, I suppose), you don't need to check in the function body. The only remaining case I can see is in a macro body, and, well, C macros aren't really all that powerful.
一般来说,用C你应该知道变量的类型。由于每个函数都有其参数的具体类型(我想,除了varargs),所以不需要检查函数体。我能看到的唯一的情况是在宏体中,而且,C宏并不是那么强大。
Further, note that C does not retain any type information into runtime. This means that, even if, hypothetically, there was a type comparison extension, it would only work properly when the types are known at compile time (ie, it wouldn't work to test whether two void *
point to the same type of data).
此外,请注意,C不会在运行时中保留任何类型信息。这意味着,即使假设存在类型比较扩展,它也只能在编译时知道类型时才能正常工作(例如,测试两个void *是否指向相同类型的数据)。
As for typeof
: First, typeof
is a GCC extension. It is not a standard part of C. It's typically used to write macros that only evaluate their arguments once, eg (from the GCC manual):
至于typeof:首先,typeof是GCC扩展。它不是c的标准部分,它通常用于编写只计算一次参数的宏,例如(来自GCC手册):
#define max(a,b) \
({ typeof (a) _a = (a); \
typeof (b) _b = (b); \
_a > _b ? _a : _b; })
The typeof
keyword lets the macro define a local temporary to save the values of its arguments, allowing them to be evaluated only once.
typeof关键字允许宏定义本地临时,以保存其参数的值,允许只计算一次。
In short, C does not support overloading; you'll just have to make a func_a(struct a *)
and func_b(struct b *)
, and call the correct one. Alternately, you could make your own introspection system:
简而言之,C不支持超载;您只需创建一个func_a(struct a *)和func_b(struct b *)并调用正确的。或者,你可以建立自己的自省系统:
struct my_header {
int type;
};
#define TYPE_A 0
#define TYPE_B 1
struct a {
struct my_header header;
/* ... */
};
struct b {
struct my_header header;
/* ... */
};
void func_a(struct a *p);
void func_b(struct b *p);
void func_switch(struct my_header *head);
#define func(p) func_switch( &(p)->header )
void func_switch(struct my_header *head) {
switch (head->type) {
case TYPE_A: func_a((struct a *)head); break;
case TYPE_B: func_b((struct b *)head); break;
default: assert( ("UNREACHABLE", 0) );
}
}
You must, of course, remember to initialize the header properly when creating these objects.
当然,您必须记住在创建这些对象时正确初始化头部。
#3
9
As other people have already said this isn't supported in the C language. You could however check the size of a variable using the sizeof()
function. This may help you determine if two variables can store the same type of data.
正如其他人已经说过的,这在C语言中不受支持。但是,您可以使用sizeof()函数检查变量的大小。这可以帮助您确定两个变量是否可以存储相同类型的数据。
Before you do that, read the comments below.
在此之前,请阅读下面的评论。
#4
5
As others have mentioned, you can't extract the type of a variable at runtime. However, you could construct your own "object" and store the type along with it. Then you would be able to check it at runtime:
正如其他人提到的,您不能在运行时提取变量的类型。但是,您可以构建自己的“对象”并将类型连同它一起存储。然后你可以在运行时检查:
typedef struct {
int type; // or this could be an enumeration
union {
double d;
int i;
} u;
} CheesyObject;
Then set the type as needed in the code:
然后根据代码的需要设置类型:
CheesyObject o;
o.type = 1; // or better as some define, enum value...
o.u.d = 3.14159;
#5
4
Gnu GCC has a builtin function for comparing types __builtin_types_compatible_p
.
Gnu GCC有一个内置函数,用于比较__builtin_types_compatible_p类型。
https://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Other-Builtins.html
https://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Other-Builtins.html
This built-in function returns 1 if the unqualified versions of the types type1 and type2 (which are types, not expressions) are compatible, 0 otherwise. The result of this built-in function can be used in integer constant expressions.
如果type1和type2类型的非限定版本(类型是类型,而不是表达式)兼容,则此内置函数返回1,否则返回0。这个内置函数的结果可以用于整数常量表达式。
This built-in function ignores top level qualifiers (e.g., const, volatile). For example, int is equivalent to const int.
这个内置函数忽略*限定符(例如const、volatile)。例如,int相当于const int。
Used in your example:
中使用的例子:
double doubleVar;
if(__builtin_types_compatible_p(typeof(doubleVar), double)) {
printf("doubleVar is of type double!");
}
#6
2
This is crazily stupid, but if you use the code:
这太愚蠢了,但是如果你使用代码:
fprintf("%x", variable)
and you use the -Wall flag while compiling, then gcc will kick out a warning of that it expects an argument of 'unsigned int' while the argument is of type '____'. (If this warning doesn't appear, then your variable is of type 'unsigned int'.)
当编译时使用-Wall标志时,gcc就会发出警告,它期望参数为'unsigned int',而参数为'____'。(如果没有出现此警告,则您的变量类型为'unsigned int'。)
Best of luck!
最好的运气!
Edit: As was brought up below, this only applies to compile time. Very helpful when trying to figure out why your pointers aren't behaving, but not very useful if needed during run time.
编辑:如下所示,这只适用于编译时间。在试图弄清楚指针为什么不正常时非常有用,但是如果在运行时需要的话就不是很有用。
#7
1
From linux/typecheck.h:
从linux / typecheck.h:
/*
* Check at compile time that something is of a particular type.
* Always evaluates to 1 so you may use it easily in comparisons.
*/
#define typecheck(type,x) \
({ type __dummy; \
typeof(x) __dummy2; \
(void)(&__dummy == &__dummy2); \
1; \
})
Here you can find explanation which statements from standard and which GNU extensions above code uses.
在这里,您可以找到来自标准的声明和以上代码使用的GNU扩展。
(Maybe a bit not in scope of the question, since question is not about failure on type mismatch, but anyway, leaving it here).
(可能不是在问题的范围内,因为问题不是关于类型不匹配的失败,而是不管怎样,把它留在这里)。
#8
0
C is statically typed language. You can't declare a function which operate on type A or type B, and you can't declare variable which hold type A or type B. Every variable has an explicitly declared and unchangeable type, and you supposed to use this knowledge.
C是静态类型语言。你不能声明一个作用于类型a或类型B的函数,也不能声明保存类型a或类型B的变量。
And when you want to know if void * points to memory representation of float or integer - you have to store this information somewhere else. The language is specifically designed not to care if char * points to something stored as int or char.
当你想知道void *是否指向浮点或整数的内存表示时,你必须将这些信息存储在其他地方。该语言是专门设计的,不关心char *指向存储为int或char的东西。
#9
0
For that purpose I have written a simple C program for that... It is in github...GitHub Link
为此,我编写了一个简单的C程序……在github……GitHub链接
Here how it works... First convert your double into a char string named s..
在这里它是如何工作的…首先将您的double转换成一个名为s的char字符串。
char s[50];
sprintf(s,"%.2f", yo);
Then use my dtype
function to determine the type... My function will return a single character...You can use it like this...
然后使用我的dtype函数来确定类型…我的函数将返回一个字符……你可以这样使用它……
char type=dtype(s);
//Return types are :
//i for integer
//f for float or decimals
//c for character...
Then you can use comparison to check it... That's it...
然后你可以用比较来检查……就是这样……
#10
0
As another answer mentioned, you can now do this in C11 with _Generic
.
正如前面提到的另一个答案,您现在可以在C11中使用_Generic实现这一点。
For example, here's a macro that will check if some input is compatible with another type:
例如,这里有一个宏,用于检查某些输入是否与另一种类型兼容:
#include <stdbool.h>
#define isCompatible(x, type) _Generic(x, type: true, default: false)
You can use the macro like so:
你可以这样使用宏:
double doubleVar;
if (isCompatible(doubleVar, double)) {
printf("doubleVar is of type double!\n"); // prints
}
int intVar;
if (isCompatible(intVar, double)) {
printf("intVar is compatible with double too!\n"); // doesn't print
}
This can also be used on other types, including structs. E.g.
这也可以用于其他类型,包括struct。如。
struct A {
int x;
int y;
};
struct B {
double a;
double b;
};
int main(void)
{
struct A AVar = {4, 2};
struct B BVar = {4.2, 5.6};
if (isCompatible(AVar, struct A)) {
printf("Works on user-defined types!\n"); // prints
}
if (isCompatible(BVar, struct A)) {
printf("And can differentiate between them too!\n"); // doesn't print
}
return 0;
}
And on typedefs.
类型定义。
typedef char* string;
string greeting = "Hello world!";
if (isCompatible(greeting, string)) {
printf("Can check typedefs.\n");
}
However, it doesn't always give you the answer you expect. For instance, it can't distinguish between an array and a pointer.
然而,它并不总是给出你所期望的答案。例如,它不能区分数组和指针。
int intArray[] = {4, -9, 42, 3};
if (isCompatible(intArray, int*)) {
printf("Treats arrays like pointers.\n");
}
// The code below doesn't print, even though you'd think it would
if (isCompatible(intArray, int[4])) {
printf("But at least this works.\n");
}
Answer borrowed from here: http://www.robertgamble.net/2012/01/c11-generic-selections.html
答案从这里借用:http://www.robertgamble.net/2012/01/c11-generic selections.html。