2017-05-11 3 views
2

조건 연산자가 활성 부분 만 평가해야하기 때문에 이러한 데모 기능은 gcc 에서 무한 루프가 아니어야합니다.C++의 조건부 연산자 버그?

Visual Studio 2015에서 올바르게 컴파일되지만 g ++ 6.3에서 무한 재귀 오류 컴파일 오류가 발생합니다. 내가 뭘 놓치고 있니?

template <int n> 
constexpr int infinite_loop_error(){ 
    return (n) ? infinite_loop_error<n - 1>() : 0; 
} 

template <int n> 
constexpr int infinite_loop_error_2(){ 
    if (n) return infinite_loop_error_2<n - 1>(); 
    else return 0; 
} 

void main() { 
    infinite_loop_error<3>(); 
    infinite_loop_error_2<3>(); 
} 
+0

표준의 모든 내용이 무한 재귀가 아니어야한다고 말합니까? 아마도 C++ 17에서 constexpr (제 생각에는?)이 해결책이 될 것입니다. – Kevin

+0

함수 템플리트의 특수화를 작성하여 문제점을 수정할 수 있음을 알고 있습니다. –

+0

to kevin : 예! "constexpr"문 (clang으로 테스트 한 경우)이 이에 적합합니다. 제안을 주셔서 감사합니다 – programmer

답변

7

이것은 MSVC의 버그이므로 프로그램을 컴파일해서는 안됩니다. 당신은 런타임 재귀와 컴파일 타임 재귀를 혼합합니다.

프로그램 만 실행에서 삼항 표현 의 한 손을 평가해야하지만 컴파일러는 여전히 삼항 표현의 두 손 (그리고 if 조건의 두 가지에 대한)에 대한 코드를 생성 할 필요가있다. 컴파일러는 멈출 수있는 지점을 찾을 수 없기 때문에 코드 생성 중에 프로그램이 실패합니다. MSVC는 최적화를 너무 일찍 적용하여 ASQ 규칙을 위반하기 때문에 "성공"합니다.

당신은 template specialization as a stopping condition 사용할 필요가 : 대신 더 재귀 할 것입니다 정의에서 infinite_loop_error<0>를 인스턴스화의

template <int n> 
constexpr int infinite_loop_error(){ 
    return (n) ? infinite_loop_error<n - 1>() : 0; 
} 

template <> 
constexpr int infinite_loop_error<0>(){ 
    return 0; 
} 

template <int n> 
constexpr int infinite_loop_error_2(){ 
    if (n) return infinite_loop_error_2<n - 1>(); 
    else return 0; 
} 

template <> 
constexpr int infinite_loop_error_2<0>(){ 
    return 0; 
} 

int main() { 
    infinite_loop_error<3>(); 
    infinite_loop_error_2<3>(); 
} 

를, 컴파일러는 당신이 그것을 제공 및 컴파일 시간 재귀가 제대로 중지 정의를 사용합니다.

+0

최고의 답변. 많은 감사합니다. – programmer