Selección genérica (C11)
Use la palabra clave _Generic
para escribir código que seleccione una expresión en tiempo de compilación según el tipo del argumento. Este funcionamiento es similar a la sobrecarga en C++, en la que el tipo de argumento selecciona a qué función llamar. En este caso, el tipo del argumento selecciona la expresión que se va a evaluar.
Por ejemplo, la expresión _Generic(42, int: "integer", char: "character", default: "unknown");
evalúa el tipo de 42
y busca el tipo coincidente, int
, en la lista. Lo encuentra y devuelve "integer"
.
generic-selection
:
_Generic
( assignment-expression
, assoc-list
)
assoc-list
:
association
assoc-list
, association
association
:
type-name
: assignment-expression
default
: assignment-expression
A la primera assignment-expression
se le llama expresión de control. El tipo de la expresión de control se determina en tiempo de compilación y se compara con la assoc-list
para encontrar la expresión que se va a evaluar y devolver. La expresión de control no se evalúa. Por ejemplo, _Generic(intFunc(), int: "integer", default: "error");
no produce una llamada en tiempo de ejecución a intFunc
.
Cuando se determina el tipo de la expresión de control, const
, volatile
y restrict
se quitan antes de compararse con assoc-list
.
No se evaluarán las entradas de la assoc-list
que no se hayan elegido.
- La
assoc-list
no puede especificar el mismo tipo más de una vez. - La
assoc-list
no puede especificar tipos compatibles entre sí, como una enumeración y el tipo subyacente de esa enumeración. - Si una selección genérica no tiene un valor predeterminado, la expresión de control solo debe tener un nombre de tipo compatible en la lista de asociaciones genérica.
Una manera de usar _Generic
se encuentra en una macro. El archivo de encabezado <tgmath.h> usa _Generic
para llamar a la función matemática correcta según el tipo de argumento. Por ejemplo, la macro para cos
asigna una llamada con un valor float a cosf
, mientras se asigna una llamada con un valor complex double a ccos
.
En el ejemplo siguiente se muestra cómo escribir una macro que identifique el tipo del argumento que le pase. Produce "unknown"
si no coincide ninguna entrada de la assoc-list
con la expresión de control:
// Compile with /std:c11
#include <stdio.h>
/* Get a type name string for the argument x */
#define TYPE_NAME(X) _Generic((X), \
int: "int", \
char: "char", \
double: "double", \
default: "unknown")
int main()
{
printf("Type name: %s\n", TYPE_NAME(42.42));
// The following would result in a compile error because
// 42.4 is a double, doesn't match anything in the list,
// and there is no default.
// _Generic(42.4, int: "integer", char: "character"));
}
/* Output:
Type name: double
*/
Compile con /std:c11
.
Windows SDK 10.0.20348.0 (versión 2104) o posterior. Consulte Windows SDK para descargar el SDK más reciente. Para obtener instrucciones sobre cómo instalar y usar el SDK para el desarrollo con C11 y C17, vea Instalación de la compatibilidad con C11 y C17 en Visual Studio.
/std
(Especificar la versión estándar del lenguaje)
Matemáticas de tipo genérico