Seleção genérica (C11)
Use a palavra-chave _Generic
para escrever um código que seleciona uma expressão em tempo de compilação com base no tipo do argumento. É semelhante à sobrecarga no C++, em que o tipo do argumento seleciona a função chamada. Nesse caso, o tipo do argumento seleciona qual expressão avaliar.
Por exemplo, a expressão _Generic(42, int: "integer", char: "character", default: "unknown");
avalia o tipo de 42
procura o tipo correspondente, int
, na lista. Ele o encontra e retorna "integer"
.
Sintaxe
generic-selection
:
_Generic
( assignment-expression
, assoc-list
)
assoc-list
:
association
assoc-list
, association
association
:
type-name
: assignment-expression
default
: assignment-expression
O primeiro assignment-expression
é chamado de expressão controladora. O tipo da expressão controladora é determinado no momento da compilação e comparado com assoc-list
para encontrar a expressão a ser avaliada e retornada. A expressão controladora não é avaliada. Por exemplo, _Generic(intFunc(), int: "integer", default: "error");
não resulta em uma chamada em runtime para intFunc
.
Quando o tipo da expressão de controle é determinado, const
, volatile
e restrict
são removidos antes de corresponder a assoc-list
.
As entradas nas assoc-list
que não são escolhidas não são avaliadas.
Restrições
- O
assoc-list
não pode especificar o mesmo tipo mais de uma vez. - O
assoc-list
não pode especificar tipos compatíveis uns com os outros, como uma enumeração e o tipo subjacente dessa enumeração. - Se uma seleção genérica não tiver um padrão, a expressão controladora precisará ter apenas um nome de tipo compatível na lista de associações genéricas.
Exemplo
Uma maneira de usar _Generic
é em uma macro. O arquivo de cabeçalho <tgmath.h> usa _Generic
para chamar a função matemática correta, dependendo do tipo de argumento. Por exemplo, a macro para cos
mapeia uma chamada com um float para cosf
, enquanto mapeia uma chamada com um duplo complexo para ccos
.
O exemplo a seguir mostra como escrever uma macro que identifica o tipo do argumento que você passa para ela. Ele produzirá "unknown"
se nenhuma entrada em assoc-list
corresponder à expressão de controle:
// 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
*/
Requisitos
Compilar com /std:c11
.
O SDK do Windows 10.0.20348.0 (versão 2104) ou posterior. Consulte o SDK do Windows para baixar o SDK mais recente. Para obter instruções sobre como instalar e usar o SDK para desenvolvimento C11 e C17, consulte Instalar o suporte C11 e C17 no Visual Studio.
Confira também
/std
(Especificar a versão padrão da linguagem)
Matemática do tipo genérico