2013-03-04 5 views
18

common_type<long, unsigned long>::typeunsigned long 때문에 표준 말한다 일체 촉진 후 피연산자 ... 관한왜 common_type <long, unsigned long> :: type = long long입니까?

[...]의 부호없는 정수 형태를 갖는 피연산자 경우 유형의 랭크 동등 이상의 순위 다른 피연산자의, 부호있는 정수 유형 피연산자는 부호없는 정수 유형으로 피연산자의 형식으로 변환해야한다

적분 추진 체제의 버그를 호출하지만, 더 큰있을 경우 것 같아하지 않기 부호있는 정수 유형 wh ich는 사용되어야하는 부호있는 피연산자와 부호없는 피연산자의 범위를 나타낼 수 있습니다.

일부 플랫폼은 긴 == long long을 가질 수 있지만, 위의 규칙이 적용될 수 있음을 알고 있습니다. 그러나 이면 더 큰 부호있는 정수형을 사용할 수 있습니까?

+4

'long long'이 'unsigned long'의 전체 범위를 포함한다는 보장이 없다고 생각합니다. 나머지 크기 사양과 같은 경우 유일한 요구 사항은 적어도 "long"만큼 많은 비트로 표현된다는 것입니다. 형식 승격은 플랫폼에 관계없이 일정하게 작동해야하므로 과부하 해결과 관련하여 일부 예측 가능성이 있습니다. – jpm

+2

'std :: common_type'은 삼항 연산자의 반환 유형을 결정하는 규칙과 일치합니다. 그 관점에서 보았을 때, 삼항 연산자가 두 가지 브랜치 중 하나보다 큰 타입을 반환한다는 것이 명백하게 잘못된 것 같습니다. –

+0

@KevinBallard 나는 그것이 분명히 틀렸다고 생각하지 않는다.분기가 다른 서명 된 값을 반환 할 때 분기 중 하나보다 큰 유형을 반환하는 것은 버그없는 것으로 보장되는 유일한 방법 인 것처럼 보입니다. – David

답변

6

우선 std :: common_type (물론 boost :: type_traits :: common_type)은 3 진 연산자를 사용하여 형식 결과를 검색합니다. 해당 유형이 결과, 일반적인 산술 변환이 일반적인 유형에 그들을 데리고에 적용됩니다 :이 경우 관련 인용 6B)

는 E2 및 E3 산술 또는 열거 형 한의 CppReference에서 온다. 이 정보를 우리가 c++ standard, 5p10에 일반적인 산술 변환에 대한 규칙을 찾을 수와

, 88 페이지

- 그렇지 않으면, 부호없는 정수 유형이 피연산자가있는 경우 더 큰 순위 다른 피연산자 유형의 등급보다 크거나 같은 경우 부호있는 정수 유형의 피연산자는 부호없는 정수 유형의 피연산자 유형으로 변환해야합니다.

그래서 기본적으로 귀하의 질문에 대한 답은 다음과 같습니다 ... 표준 그렇게 말한다 때문이다.

그러나이 동작이 예상치 않게 발생하는 것은 아닙니다.

#include <iostream> 
#include <typeinfo> 
#include <type_traits> 

int main(int argc, const char* argv[]) 
{ 

    std::cout << typeid(std::common_type<char, unsigned char>::type).name() << std::endl; 
    // I would expect "short", and the result is "int", ok so far. 

    std::cout << typeid(std::common_type<short, unsigned short>::type).name() << std::endl; 
    // I would expect "int", and the result is "int", yay. 

    std::cout << typeid(std::common_type<int, unsigned int>::type).name() << std::endl; 
    // I would expect "long", but the result is "unsigned int" 

    std::cout << typeid(std::common_type<long, unsigned long>::type).name() << std::endl; 
    // I would expect "long long", but the result is "unsigned long" 


    // So this usual arithmetic conversion can lead to unexpected behavior: 
    auto var_auto = true ? var_i : var_ui; 
    std::cout << typeid(var_auto).name() << std::endl; // unsigned int 
    std::cout << var_auto << std::endl;     // 4294967173 

    return 0; 
} 

을하지만 현재의 행동이 문제가 있음을 known이며, proposal가 놀라움의 일부를 제거하기 위해 존재 : 여기에 시도 빠른 실행 가능한 예입니다.

-hannes

+0

그렇다면 귀하의 질문은 무엇입니까? 나는 왜 common_type :: type = long long? "이라고 대답했다. 당신의보기는 나의보기보다는 정보를 더 추가하지 않는다, 나 틀린 경우에 저를 정정하십시오. 그러나 물론 1 <* MaxULong * -1 ... –

+0

표준에서 실제로 그것이 그 방법이라고 말하면서, 표준이 그렇게 말하고 있기 때문에이 방법임을 다시금 알 수있는 대답이 필요 없다는 것이 분명했습니다. . 하지만 제가 말씀 드렸듯이, 당신이 아래쪽에 링크를 가지고있어서 다행입니다. 관련성이 높고 부분적인 대답입니다. (알려진 '문제'이지만, 왜 이런 식으로 시작했는지 보여주지는 않습니다.) – David

관련 문제