Namespaces
Variants

Generic selection (since C11)

From cppreference.net

제어 표현식의 타입을 기반으로 컴파일 타임에 여러 표현식 중 하나를 선택하는 방법을 제공합니다

목차

구문

_Generic ( controlling-expression , association-list ) (C11부터)

여기서 association-list 는 쉼표로 구분된 연관 목록이며, 각 연관은 다음 구문을 가집니다

type-name : expression
default : expression

여기서

type-name - 가변 수정되지 않은(즉, VLA 또는 VLA에 대한 포인터가 아닌) 모든 완전한 객체 타입
controlling-expression - default 연관이 사용되지 않는 경우 해당 타입이 type-name 중 하나와 호환되어야 하는 모든 표현식( 쉼표 연산자 제외)
expression - 모든 타입과 값 범주를 가진 모든 표현식( 쉼표 연산자 제외)

type-name 이 두 개 이상 association-list 에서 호환 가능한 타입 을 지정해서는 안 됩니다. default 키워드를 사용하는 연결은 오직 하나만 존재할 수 있습니다. default 가 사용되지 않고 type-name 중 어느 것도 제어 표현식의 타입과 호환되지 않을 경우, 프로그램은 컴파일되지 않습니다.

설명

먼저, controlling-expression 의 타입은 lvalue conversions 를 거칩니다. 변환은 타입 영역에서만 수행됩니다: 최상위 cvr-qualifiers와 atomicity를 버리고 배열-포인터/함수-포인터 변환을 제어 표현식의 타입에 적용하며, 부수 효과를 발생시키거나 값을 계산하지 않습니다.

변환 후의 타입은 연관 목록의 type-name 들과 비교됩니다.

타입이 어느 하나의 연관의 type-name 호환 가능하다면 , 제네릭 선택의 타입, 값, 그리고 값 범주 는 해당 type-name 에 대해 콜론 뒤에 나타나는 expression 의 타입, 값, 그리고 값 범주와 동일합니다.

만약 type-name 들 중 어느 것도 controlling-expression 의 타입과 호환되지 않고, default 연관이 제공된 경우, 제네릭 선택의 타입, 값, 값 범주는 default : 레이블 뒤의 표현식의 타입, 값, 값 범주와 동일합니다.

참고 사항

controlling-expression 과 선택되지 않은 선택문들의 expression 은 절대로 평가되지 않습니다.

lvalue 변환 때문에, "abc" char * 와 일치하고 char [ 4 ] 와는 일치하지 않으며, ( int const ) { 0 } int 와 일치하고 const int 와는 일치하지 않습니다.

모든 값 카테고리 는 함수 지정자와 void 표현식을 포함하여 제네릭 선택에서 표현식 으로 허용되며, 선택된 경우 제네릭 선택 자체도 동일한 값 카테고리를 가집니다.

C99에서 도입된 type-generic math macros <tgmath.h> 에서 컴파일러별 방식으로 구현되었습니다. C11에서 도입된 generic selections는 프로그래머가 유사한 타입 의존적 코드를 작성할 수 있는 능력을 부여했습니다.

제네릭 선택은 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 적용 대상 게시된 동작 올바른 동작
DR 481 C11 제어 표현식이 lvalue 변환을 거치는지 여부가 불충분하게 명시됨 lvalue 변환을 거침

참고문헌

  • C23 표준 (ISO/IEC 9899:2024):
  • 6.5.1.1 제네릭 선택 (p: TBD)
  • C17 표준 (ISO/IEC 9899:2018):
  • 6.5.1.1 일반 선택 (p: 56-57)
  • C11 표준 (ISO/IEC 9899:2011):
  • 6.5.1.1 Generic selection (p: 78-79)

참고 항목

C++ documentation for Templates