consteval 함수가 정의되지 않은 동작을 허용하는 이유는 무엇입니까?


16

C ++에는 상수 표현식의 매우 깔끔한 속성이 있습니다. 평가에는 정의되지 않은 동작 ( 7.7.4.7 ) 이있을 수 없습니다 .

추상 기계의 규칙 ([intro.execution])에 따라 e의 평가가 다음 중 하나를 평가하지 않는 한, 표현식 e는 핵심 상수 표현식입니다.

  • ...

  • 이 문서의 [intro] ~ [cpp]에 지정된대로 정의되지 않은 동작을 갖는 연산 [참고 : 예를 들어 부호있는 정수 오버플로 ([expr.prop]), 특정 포인터 산술 ([expr.add]) 포함, 0으로 나누기, 또는 특정 시프트 연산 – 끝 참고];

의 값을 저장하려고 13!A가에 constexpr int참으로 멋진 컴파일 오류를 얻을 수를 :

constexpr int f(int n) 
{
    int r = n--;
    for (; n > 1; --n) r *= n;
    return r;
}

int main() 
{
    constexpr int x = f(13);
    return x;
}

산출:

9:19: error: constexpr variable 'x' must be initialized by a constant expression
    constexpr int x = f(13);
                  ^   ~~~~~
4:26: note: value 3113510400 is outside the range of representable values of type 'int'
    for (; n > 1; --n) r *= n;
                         ^
9:23: note: in call to 'f(3)'
    constexpr int x = f(13);
                      ^
1 error generated.

(BTW가 왜 '(f) (f)'(f)에 대한 호출입니까? '

그럼, 제거 constexpr에서 x,하지만 할 fconsteval. 문서 에 따르면 :

consteval-함수가 즉각적인 함수임을 지정합니다. 즉, 함수를 호출 할 때마다 컴파일 타임 상수가 생성되어야합니다.

그러한 프로그램이 다시 컴파일 오류를 일으킬 것으로 예상합니다. 그러나 대신 프로그램은 UB로 컴파일하고 실행합니다 .

왜 그런 겁니까?

UPD : 의견 제시 자들은 이것이 컴파일러 버그라고 제안했습니다. 나는 그것을보고했다 : https://bugs.llvm.org/show_bug.cgi?id=43714


2
in call to 'f(3)'- 이건 이상해! 전의. f(123)clang 을 넣으면 에 대해 경고합니다 in call to 'f(119)'.
KamilCuk

나는 이것이 단지 버그라고 생각한다. 표준은 "즉시 호출은 일정한 표현이어야한다"는 것이 분명하다. 그러나 더 복잡한 일이있을 수도 있습니다 (즉, 요구 사항이 제거되고 Clang이 새로운 행동을 구현하고있을 수도 있습니다).
Brian

3
컴파일러 버그. 여기서 볼 것이 없습니다.
TC

1
@JesperJuhl 완료.
Mikhail

4
@StoryTeller 정수는 2의 보수이지만 오버플로는 여전히 정의되어 있지 않습니다.
Barry

답변:


2

이것은 컴파일러 버그입니다. 또는 더 정확하게 말하면 이것은 "구현되지 않은"기능입니다 ( bugzilla의 주석 참조 ).

https://clang.llvm.org/cxx_status.html 에 따르면 consteval이 아직 구현되지 않은 것 같습니다.

(키워드가 추가되었지만 실제 구현 지원이 아닌 것 같습니다)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.