Generic selection (since C11)
Предоставляет способ выбора одного из нескольких выражений во время компиляции на основе типа управляющего выражения
Содержание |
Синтаксис
_Generic
(
управляющее-выражение
,
список-ассоциаций
)
|
(начиная с C11) | ||||||||
где association-list представляет собой список ассоциаций, разделенных запятыми, каждый из которых имеет синтаксис
имя-типа
:
выражение
|
|||||||||
default
:
выражение
|
|||||||||
где
| type-name | - | любой полный тип объекта , который не является вариативно-модифицированным (то есть не VLA и не указатель на VLA). |
| controlling-expression | - | любое выражение (кроме оператора запятой ), тип которого должен быть совместим с одним из type-name , если не используется ассоциация default |
| expression | - | любое выражение (кроме оператора запятой ) любого типа и категории значения |
Никакие два type-name в association-list не могут указывать совместимые типы . Может существовать только одна ассоциация, использующая ключевое слово default . Если default не используется и ни один из type-name не совместим с типом управляющего выражения, программа не скомпилируется.
Объяснение
Сначала тип controlling-expression подвергается lvalue conversions . Преобразование выполняется только в области типов: оно отбрасывает cvr-квалификаторы верхнего уровня и атомарность, а также применяет преобразования массив-в-указатель/функция-в-указатель к типу управляющего выражения, не инициируя побочных эффектов и не вычисляя никаких значений.
Тип после преобразования сравнивается с type-name из списка ассоциаций.
Если тип совместим с type-name одной из ассоциаций, тогда тип, значение и категория значения универсальной выборки являются типом, значением и категорией значения expression , который следует после двоеточия для этого type-name .
Если ни одно из
type-name
не совместимо с типом
controlling-expression
, и предоставлена ассоциация
default
, тогда тип, значение и категория значения универсальной выборки соответствуют типу, значению и категории значения выражения после метки
default :
.
Примечания
Управляющее выражение и выражения в ветвях, которые не выбраны, никогда не вычисляются.
Из-за преобразований lvalue, "abc" соответствует char * , а не char [ 4 ] , и ( int const ) { 0 } соответствует int , а не const int .
Все категории значений , включая обозначения функций и void-выражения, допустимы в качестве expression s в универсальном выборе, и если выбраны, сам универсальный выбор имеет ту же категорию значений.
Обобщенные математические макросы из <tgmath.h> , представленные в C99, были реализованы специфичным для компилятора способом. Обобщенные выборки, представленные в C11, предоставили программистам возможность писать аналогичный типозависимый код.
Универсальная выборка аналогична перегрузке в C++ (когда одна из нескольких функций выбирается во время компиляции на основе типов аргументов), за исключением того, что она осуществляет выбор между произвольными выражениями.
Ключевые слова
Пример
#include <math.h> #include <stdio.h> // Возможная реализация макроса tgmath.h 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)); // выбирает cbrt по умолчанию printf("cbrtf(3.375) = %f\n", cbrt(y)); // преобразует const float в float, // затем выбирает cbrtf }
Вывод:
cbrt(8.0) = 2.000000 cbrtf(3.375) = 1.500000
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| DR 481 | C11 | было недостаточно определено, подвергается ли управляющее выражение преобразованиям lvalue | подвергается |
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
-
- 6.5.1.1 Обобщённый выбор (стр.: TBD)
- Стандарт C17 (ISO/IEC 9899:2018):
-
- 6.5.1.1 Обобщённый выбор (стр: 56-57)
- Стандарт C11 (ISO/IEC 9899:2011):
-
- 6.5.1.1 Обобщённый выбор (стр. 78-79)
Смотрите также
|
C++ documentation
для
Templates
|