Spec-Zone.ru › C

Обобщённый выбор (с 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++ (где одна из нескольких функций выбирается во время компиляции на основе типов аргументов), за исключением того, что он производит выбор между произвольными выражениями.

Ключевые слова

_Generic, default

Пример

#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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API