Usual arithmetic conversions
많은 이항 연산자는 arithmetic 또는 enumeration 타입의 피연산자를 기대하며, 유사한 방식으로 변환을 유발하고 결과 타입을 생성합니다. 목적은 공통 타입을 생성하는 것이며, 이는 결과의 타입이기도 합니다. 이러한 패턴을 usual arithmetic conversions (일반 산술 변환)이라고 합니다.
목차 |
정의
일반적인 산술 변환은 다음과 같이 정의됩니다:
스테이지 1
두 피연산자에 lvalue-to-rvalue conversion 을 적용하며, 결과로 생성된 prvalue들은 나머지 처리 과정에서 원래 피연산자 대신 사용됩니다.
Stage 2
|
(since C++11) |
Stage 3
|
(C++26부터) |
단계 4
- 피연산자 중 하나가 floating-point type 인 경우, 다음 규칙들이 적용됩니다:
-
- 두 피연산자가 동일한 타입을 가질 경우, 추가 변환은 수행되지 않습니다.
- 그렇지 않고 피연산자 중 하나가 부동소수점 타입이 아닐 경우, 해당 피연산자는 다른 피연산자의 타입으로 변환됩니다.
- 그렇지 않고 피연산자 타입들의 floating-point conversion ranks 가 순서가 지정되어 있지만 (since C++23) 동일하지 않을 경우, 더 낮은 floating-point conversion rank를 가진 타입의 피연산자는 다른 피연산자의 타입으로 변환됩니다.
|
(C++23부터) |
- 그렇지 않으면, 두 피연산자가 모두 정수 타입인 경우 다음 단계로 진행합니다.
Stage 5
두 피연산자는 공통 타입
C
로 변환됩니다.
T1
과
T2
를 피연산자의 승격된 타입(
정수 승격 규칙에 따라
)으로 가정할 때, 다음 규칙들이
C
를 결정하기 위해 적용됩니다:
-
만약
T1과T2가 동일한 타입이라면,C는 해당 타입입니다. -
그렇지 않고
T1과T2가 모두 부호 있는 정수 타입이거나 모두 부호 없는 정수 타입인 경우,C는 더 높은 정수 변환 순위 를 가진 타입입니다. -
그렇지 않으면,
T1과T2중 하나는 부호 있는 정수 타입S이고, 다른 하나는 부호 없는 정수 타입U입니다. 다음 규칙들을 적용합니다:
-
-
U의 정수 변환 등급이S의 정수 변환 등급보다 크거나 같으면,C는U입니다. -
그렇지 않고,
S가U의 모든 값을 표현할 수 있으면,C는S입니다. -
그 외의 경우,
C는S에 해당하는 부호 없는 정수 타입입니다.
-
|
한 피연산자가 열거형 타입이고 다른 피연산자가 다른 열거형 타입 또는 부동소수점 타입인 경우, 이 동작은 사용이 권장되지 않습니다. |
(since C++20)
(until C++26) |
정수 변환 순위
모든 integer type 은 다음과 같이 정의된 integer conversion rank 를 가집니다:
- char 및 signed char (만약 char 가 부호 있는 경우)를 제외한 어떠한 두 부호 있는 정수 타입도 동일한 표현을 가지더라도 동일한 순위를 가지지 않습니다.
- 부호 있는 정수 타입의 순위는 더 작은 너비를 가진 어떤 부호 있는 정수 타입의 순위보다 큽니다.
- 다음 정수 타입들의 순위는 아래 순서대로 감소합니다:
|
(C++11부터) |
-
- long
- int
- short
- signed char
- 부호 없는 정수형의 순위는 해당 부호 있는 정수형의 순위와 동일합니다.
|
(since C++11) |
- bool 의 순위는 모든 표준 정수형의 순위보다 낮습니다.
- 인코딩 문자형( char , char8_t (C++20부터) , char16_t , char32_t , (C++11부터) 및 wchar_t )의 순위는 각각의 기반 타입 순위와 동일하며, 이는 다음을 의미합니다:
-
- char 의 랭크는 signed char 와 unsigned char 의 랭크와 동일합니다.
|
(C++20부터) |
|
(C++11부터) |
-
- wchar_t 의 랭크는 구현에서 정의된 기반 타입의 랭크와 동일합니다.
|
(since C++11) |
-
모든 정수 타입
T1,T2, 그리고T3에 대해,T1이T2보다 더 높은 순위를 가지고T2가T3보다 더 높은 순위를 가지면,T1은T3보다 더 높은 순위를 가집니다.
정수 변환 순위는 또한 integral promotion 의 정의에 사용됩니다.
부동소수점 변환 순위 및 하위 순위
부동소수점 변환 순위
모든 floating-point type 은 다음과 같이 정의된 floating-point conversion rank 를 가집니다:
-
표준 부동소수점 타입의 순위는 다음과 같이 감소합니다:
- long double
- double
- float
|
(C++23부터) |
부동소수점 변환 서브순위동일한 부동소수점 변환 순위를 가지는 부동소수점 타입들은 부동소수점 변환 서브순위 에 따라 정렬됩니다. 서브순위는 동일한 순위를 가진 타입들 사이에서 완전 순서를 형성합니다.
|
(C++23부터) |
사용법
부동 소수점 변환 순위와 하위 순위는 또한 다음을 위해 사용됩니다
- 서로 다른 부동소수점 타입 간 변환이 암시적 변환 이 가능한지, 아니면 축소 변환 인지 판단합니다,
- 오버로드 해결에서 변환 시퀀스 를 구분합니다,
|
(C++23부터) |
- std::complex 의 변환 생성자 가 explicit인지 여부를 결정하거나,
- 서로 다른 부동소수점 타입의 인자들이 일반 또는 특수 수학 함수에 전달될 때 공통 부동소수점 타입을 결정합니다.
결함 보고서
다음 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.
| DR | 적용 대상 | 게시된 동작 | 올바른 동작 |
|---|---|---|---|
| CWG 1642 | C++98 | 일반 산술 변환이 lvalue를 포함할 수 있음 | 먼저 lvalue-to-rvalue 변환을 적용 |
| CWG 2528 | C++20 |
unsigned
char
와
unsigned
int
간의 삼중 비교는
중간 정수 승격으로 인해 형식 오류 발생 [1] |
피연산자를 실제로 승격시키지 않고
승격된 타입을 기반으로 공통 타입 결정 [2] |
| CWG 2892 | C++98 |
두 피연산자가 동일한 부동소수점 타입일 때
"더 이상 변환이 필요하지 않음"의 의미가 불명확 |
"더 이상 변환이 수행되지 않음"으로 변경 |
- ↑ 해결 이전에는, unsigned char 가 5단계 시작 시점에 int 로 승격된 후, unsigned int 로 변환됩니다. 그러나 후자의 변환은 축소 변환(narrowing)이므로 삼중 비교(three-way comparison)가 올바르지 않은 형태(ill-formed)가 됩니다.
- ↑ 해결 이후에도 공통 타입(common type)은 여전히 unsigned int 입니다. 차이점은 unsigned char 가 중간 정수 승격(integral promotion) 없이 직접 unsigned int 로 변환된다는 것입니다. 이 변환은 축소 변환이 아니므로 삼중 비교가 올바른 형태(well-formed)입니다.