Namespaces
Variants

Generic selection (since C11)

From cppreference.net

Предоставляет способ выбора одного из нескольких выражений во время компиляции на основе типа управляющего выражения

Содержание

Синтаксис

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

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

_Generic , default

Пример

#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