2013-06-22 2 views
15
경우

다음 코드 고려 다음 C++ 표준 [expr.cond]에 따른의 유형 '?'첫 번째 피연산자는 상수 식

void f(float x) 
{ 
    x * (true ? 1.f : 0.0); 
} 

declval(bool) ? declval(float) : declval(double) 유형이다 double한다.

void f(float x) 
{ 
    double(x) * 1.0; 
} 

또는 경우에 최적화 ?:의 첫 번째 피연산자는 컴파일 타임 상수 표현 할 수있는 문이 :

이 위의 코드는 동등해야한다는 것을 의미합니까?

+0

'난독 화 된 C++ 콘테스트'에서 온 것입니까? '사실이야? 1.0f : ...'는 항상 1.0f로 평가되지만, 1.0f로 곱하는 것이 맞습니까? –

+1

@ ott-- 그 대답은 질문이 실제로 무엇에 관한 것인지에만 집중할 수있는 방식으로 질문을 표현하는 좋은 방법입니다. 거의 모든 상수는 질문의 요점이 아닐지라도 반올림에 초점을 맞춘 답을 얻습니다. – hvd

+4

표현식은 항상 하나의 유형 만 가질 수 있으므로'something? a : b는 무엇이든 상관없이 항상 같아야합니다. – Xeo

답변

10

C++ 컴파일러는 적합 프로그램의 "관찰 가능한 동작"(§ 1.9p1, 소위 "있는 그대로"규칙)을 변경하지 않는다면 적합하다고 판단하여 최적화 할 수 있습니다.

예를 들어, 주어진 플랫폼에서 1.0으로 곱하는 것이 잠재적 인 함정이없는 항등 변환 인 것으로 알려진 경우 실제로 곱셈을 수행 할 필요가 없습니다. (NaN 값에 1.0을 곱한 값이 트랩 될 가능성이 있기 때문에 특정 아키텍처에서는 그렇지 않을 수도 있습니다.) 그러나 컴파일러는 동일한 상황에서 동일한 트랩을 생성하는 다른 연산에 의한 곱셈을 대체 할 수도 있습니다 .

트랩이없고 1.0 곱셈이 항등 변환이라고 가정하면 표준에서 float 값 집합이 집합의 하위 집합이어야하므로 함수 f의 전체 본문을 제거 할 수 있습니다. double 값 (아마도 동일한 세트). 따라서 float-> double-> float 왕복은 원래 값이나 트랩으로 돌아 가야합니다. (§ 3.9.1p8 : "유형 float의 값 집합은 double 유형의 값 집합의 하위 집합입니다."§ 4.8p1 : "부동 소수점 유형의 prvalue는 다른 부동 소수점의 prvalue로 변환 될 수 있습니다 소스 값이 대상 유형에서 정확하게 표현 될 수있는 경우 변환 결과는 정확한 표현입니다. ")

그래, 최적화가 가능할 수 있습니다. 그러나 형식을 관찰 할 수있는 경우 (예 : 표현식이 템플릿 공제에 사용되거나 decltype의 피연산자로 사용되는 경우) ?: 표현식의 유형에는 영향을주지 않습니다.

14

예, 위의 코드가 동일 함을 의미합니다.

#include <iostream> 
#include <typeinfo> 

int main() { 
    float x = 3.; 
    auto val = x * (true ? 1.f : 0.0); 
    std::cout << typeid(val).name() << std::endl; 
} 

그리고 C++ 11 type traits를 사용하는 또 다른 방법 :

RTTI 우리가 적어도 두 clangg++은 표준 준수를 것을 확인하고이 프로그램의 출력으로 (예 : 이중) d을 줄 수 사용

#include <iostream> 
#include <typeinfo> 

int main() { 
    float x = 3.; 
    auto val = x * (true ? 1.f : 0.0); 
    std::cout << std::boolalpha << 
     std::is_same<decltype(val), double>::value << std::endl; 
} 

출력 true.