Namensräume
Varianten
Aktionen

Generische Auswahl (seit C11)

Von cppreference.com
< c‎ | Sprache

Bietet eine Möglichkeit, zur Compile-Zeit einen von mehreren Ausdrücken basierend auf dem Typ eines Kontrollausdrucks auszuwählen

Inhalt

[bearbeiten] Syntax

_Generic ( Kontrollausdruck , Assoziationsliste ) (seit C11)

wobei Assoziationsliste eine kommagetrennte Liste von Assoziationen ist, von denen jede die folgende Syntax hat:

Typname : Ausdruck
default : Ausdruck

wobei

Typname - Jeder vollständige Objekttyp, der nicht variablenmodifiziert ist (d. h. kein VLA oder Zeiger auf VLA).
Kontrollausdruck - Jeder Ausdruck (außer dem Kommaoperator), dessen Typ mit einem der Typnamen kompatibel sein muss, wenn die default-Assoziation nicht verwendet wird.
expression - Jeder Ausdruck (außer dem Kommaoperator) beliebigen Typs und beliebiger Wertkategorie.

Keine zwei Typnamen in der Assoziationsliste dürfen kompatible Typen angeben. Es darf nur eine Assoziation geben, die das Schlüsselwort default verwendet. Wenn default nicht verwendet wird und keiner der Typnamen mit dem Typ des Kontrollausdrucks kompatibel ist, kompiliert das Programm nicht.

[bearbeiten] Erklärung

Zuerst unterliegt der Typ des Kontrollausdrucks Lvalue-Konvertierungen. Die Konvertierung erfolgt nur im Typdomäne: Sie verwirft die cvr-Qualifizierer auf oberster Ebene und die Atomizität und wendet Array-zu-Zeiger/Funktion-zu-Zeiger-Transformationen auf den Typ des Kontrollausdrucks an, ohne Nebenwirkungen auszulösen oder Werte zu berechnen.

Der Typ nach der Konvertierung wird mit den Typnamen aus der Liste der Assoziationen verglichen.

Wenn der Typ mit dem Typnamen einer der Assoziationen kompatibel ist, dann sind Typ, Wert und Wertkategorie der generischen Auswahl der Typ, der Wert und die Wertkategorie des Ausdrucks, der nach dem Doppelpunkt für diesen Typnamen steht.

Wenn keiner der Typnamen mit dem Typ des Kontrollausdrucks kompatibel ist und die default-Assoziation bereitgestellt wird, dann sind Typ, Wert und Wertkategorie der generischen Auswahl der Typ, der Wert und die Wertkategorie des Ausdrucks nach dem Label default :.

[bearbeiten] Hinweise

Der Kontrollausdruck und die Ausdrücke der nicht ausgewählten Optionen werden niemals ausgewertet.

Aufgrund der Lvalue-Konvertierungen entspricht "abc" char* und nicht char[4] und (int const){0} entspricht int und nicht const int.

Alle Wertkategorien, einschließlich Funktionsdeskriptoren und void-Ausdrücken, sind als Ausdrücke in einer generischen Auswahl zulässig, und wenn sie ausgewählt werden, hat die generische Auswahl selbst dieselbe Wertkategorie.

Die Typ-generischen mathematischen Makros aus <tgmath.h>, die in C99 eingeführt wurden, wurden compiler-spezifisch implementiert. Generische Auswahlen, die in C11 eingeführt wurden, gaben den Programmierern die Möglichkeit, ähnlichen typabhängigen Code zu schreiben.

Generische Auswahl ist ähnlich wie Überladung in C++ (wo eine von mehreren Funktionen zur Compile-Zeit basierend auf den Argumenttypen ausgewählt wird), außer dass sie die Auswahl zwischen beliebigen Ausdrücken ermöglicht.

[bearbeiten] Schlüsselwörter

_Generic, default

[bearbeiten] Beispiel

#include <math.h>
#include <stdio.h>
 
// Possible implementation of the tgmath.h macro cbrt
#define cbrt(X) _Generic((X),     \
              long double: cbrtl, \
                  default: cbrt,  \
                    float: cbrtf  \
              )(X)
 
int main(void)
{
    double x = 8.0;
    const float y = 3.375;
    printf("cbrt(8.0) = %f\n", cbrt(x));    // selects the default cbrt
    printf("cbrtf(3.375) = %f\n", cbrt(y)); // converts const float to float,
                                            // then selects cbrtf
}

Ausgabe

cbrt(8.0) = 2.000000
cbrtf(3.375) = 1.500000

[bearbeiten] Fehlerberichte

Die folgenden verhaltensändernden Defect Reports wurden rückwirkend auf zuvor veröffentlichte C-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
DR 481 C11 Es war unter-spezifiziert, ob der Kontrollausdruck Lvalue-Konvertierungen durchläuft. Er durchläuft sie.

[bearbeiten] Referenzen

  • C23-Standard (ISO/IEC 9899:2024)
  • 6.5.1.1 Generische Auswahl (S. TBD)
  • C17-Standard (ISO/IEC 9899:2018)
  • 6.5.1.1 Generische Auswahl (S. 56-57)
  • C11-Standard (ISO/IEC 9899:2011)
  • 6.5.1.1 Generische Auswahl (S. 78-79)

[bearbeiten] Siehe auch

C++-Dokumentation für Templates