Обобщённый выбор (с C11)
Предоставляет способ выбора одного из нескольких выражений во время компиляции, основанный на типе управляющего выражения
Синтаксис
_Generic ( управляющее выражение , список ассоциаций ) | (с C11) |
где список ассоциаций — это список ассоциаций, разделённых запятыми, каждая из которых имеет синтаксис
имя типа : выражение | ||
default : выражение |
где
| имя типа | - | любой полный тип объекта, который не является изменённым с помощью переменной (то есть не VLA или указатель на VLA). |
| управляющее выражение | - | любое выражение (кроме оператора запятой), тип которого должен быть совместим с одним из имен типов, если default ассоциация не используется |
| выражение | - | любое выражение (кроме оператора запятой) любого типа и категории значения |
Никакие два имени типа в списке ассоциаций не могут указывать совместимые типы. Может быть только одна ассоциация, которая использует ключевое слово default. Если default не используется и ни одно из имен типов не совместимо с типом управляющего выражения, программа не будет скомпилирована.
Объяснение
Сначала тип управляющего выражения подвергается преобразованиям lvalue. Преобразование выполняется только в области типов: оно отбрасывает квалификаторы cvr и атомарность верхнего уровня и применяет преобразования массив-указатель/функция-указатель к типу управляющего выражения без запуска побочных эффектов или вычисления значений.
Тип после преобразования сравнивается с именами типов из списка ассоциаций.
Если тип совместим с именем типа одной из ассоциаций, то тип, значение и категория значения обобщённого выбора являются типом, значением и категорией значения выражения, которое следует после двоеточия для этого имени типа.
Если ни одно из имён типов не совместимо с типом управляющего выражения, и default ассоциация предоставлена, тогда тип, значение и категория значения обобщённого выбора являются типом, значением и категорией значения выражения после метки default :.
Примечания
Управляющее выражение и выражения выборов, которые не выбраны, никогда не оцениваются.
Из-за преобразований lvalue, "abc" соответствует char*, а не char[4], и (int const){0} соответствует int, а не const int.
Все категории значений, включая указатели на функции и выражения void, разрешены в качестве выражений в обобщённом выборе, и если выбран, обобщённый выбор сам имеет ту же категорию значения.
Макросы типо-обобщённой математики из <tgmath.h>, представленные в C99, были реализованы специфичным для компилятора способом. Обобщённые выборы, представленные в C11, дали программистам возможность писать похожий зависимый от типа код.
Обобщённый выбор похож на перегрузку в C++ (где одна из нескольких функций выбирается во время компиляции на основе типов аргументов), за исключением того, что он производит выбор между произвольными выражениями.
Ключевые слова
Пример
#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
}Вывод:
cbrt(8.0) = 2.000000 cbrtf(3.375) = 1.500000
Отчёты о дефектах
Следующие отчёты о дефектах, изменяющих поведение, были применены ретроактивно к ранее опубликованным стандартам C.
| DR | Применён к | Поведение, как опубликовано | Правильное поведение |
|---|---|---|---|
| DR 481 | C11 | не было точно указано, подвергается ли управляющее выражение преобразованиям lvalue | подвергается |
Ссылки
- Стандарт C23 (ISO/IEC 9899:2023):
- 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++ по Шаблонам |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/c/language/generic