Wybór ogólny (C11)
Użyj słowa kluczowego _Generic
, aby napisać kod, który wybiera wyrażenie w czasie kompilacji na podstawie typu argumentu. Jest on podobny do przeciążenia w języku C++, w którym typ argumentu wybiera funkcję do wywołania. W tym przypadku typ argumentu wybiera wyrażenie do obliczenia.
Na przykład wyrażenie _Generic(42, int: "integer", char: "character", default: "unknown");
oblicza typ 42
i wyszukuje pasujący typ , int
na liście. Znajduje go i zwraca wartość "integer"
.
Składnia
generic-selection
:
_Generic
( assignment-expression
, assoc-list
)
assoc-list
:
association
assoc-list
, association
association
:
type-name
: assignment-expression
default
: assignment-expression
Pierwszy assignment-expression
jest nazywany wyrażeniem sterującym. Typ wyrażenia sterującego jest określany w czasie kompilacji i dopasowany do assoc-list
elementu w celu znalezienia wyrażenia, które ma być obliczane i zwracane. Wyrażenie sterujące nie jest oceniane. Na przykład _Generic(intFunc(), int: "integer", default: "error");
nie powoduje wywołania w czasie wykonywania polecenia .intFunc
Gdy typ wyrażenia sterującego zostanie określony, const
, volatile
i restrict
zostaną usunięte przed dopasowaniem względem assoc-list
elementu .
Wpisy w elemecie assoc-list
, które nie są wybrane, nie są oceniane.
Ograniczenia
- Nie
assoc-list
można określić tego samego typu więcej niż raz. - Nie
assoc-list
można określić typów, które są ze sobą zgodne, takie jak wyliczenie i podstawowy typ tego wyliczenia. - Jeśli wybór ogólny nie ma wartości domyślnej, wyrażenie sterujące musi mieć tylko jedną zgodną nazwę typu na liście skojarzeń ogólnych.
Przykład
Jednym ze sposobów użycia _Generic
jest makro. Plik nagłówkowy <tgmath.h> używa _Generic
metody do wywoływania właściwej funkcji matematycznej w zależności od typu argumentu. Na przykład makro mapuje cos
wywołanie z zmiennoprzecinkowym na cosf
, mapując wywołanie ze złożonym podwójnym ccos
na .
W poniższym przykładzie pokazano, jak napisać makro, które identyfikuje typ przekazanego do niego argumentu. "unknown"
Tworzy, jeśli w wyrażeniu sterującym assoc-list
nie ma wpisu zgodnego z wyrażeniem sterującym:
// 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
*/
Wymagania
Skompiluj za pomocą polecenia /std:c11
.
Windows SDK 10.0.20348.0 (wersja 2104) lub nowsza. Zobacz Zestaw Windows SDK , aby pobrać najnowszy zestaw SDK. Aby uzyskać instrukcje dotyczące instalowania i używania zestawu SDK dla programowania C11 i C17, zobacz Instalowanie obsługi C11 i C17 w programie Visual Studio.
Zobacz też
/std
(Określ wersję standardową języka)
Matematyka ogólna typu