Generic selection (since C11)
제어 표현식의 타입을 기반으로 컴파일 타임에 여러 표현식 중 하나를 선택하는 방법을 제공합니다
목차 |
구문
_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++의 오버로딩(인수의 타입에 따라 컴파일 시간에 여러 함수 중 하나를 선택하는 방식)과 유사하지만, 임의의 표현식들 사이에서 선택을 수행한다는 점이 다릅니다.
키워드
예제
#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
|