TL; DR : 그 소리를 들어
는 명령 줄 인수 -fconstexpr-steps=1271242
를 원하는 당신은 계산 이상의 -fconstexpr-depth=27
재귀 방법이 필요하지 않습니다 피보나치 수는 재귀 깊이가별로 필요하지 않습니다. fib(n)
에 필요한 깊이는 실제로는 n
입니다. 이것은 가장 긴 호출 체인이 fib(i-1)
재귀 호출을 통과하기 때문입니다.
constexpr auto fib_1 = fib_cxpr(3); // fails with -fconstexpr-depth=2, works with -fconstexpr-depth=3
constexpr auto fib_1 = fib_cxpr(4); // fails with -fconstexpr-depth=3, works with -fconstexpr-depth=4
따라서 -fconstexpr-depth
은 중요한 설정이 아닙니다. 그 소리는 메시지 생성,
constexpr auto fib_1 = fib_cxpr(27);
우리는 그 한계를 공격해야하는, -fconstexpr-depth=26
로 컴파일 :
는 또한, 오류 메시지도 차이를 나타냅니다
note: constexpr evaluation exceeded maximum depth of 26 calls
을하지만 -fconstexpr-depth=27
컴파일, 충분한 깊이 인 메시지는 다음과 같이 메시지를 생성합니다.
그래서 clang은 재귀 깊이와 '단계 제한'의 두 가지 실패를 구분한다는 것을 알고 있습니다.
'연타 최대 단계 제한'에 대한 상위 Google 결과
명령 줄 옵션의 구현을 포함하여이 기능을 구현하는 그 소리 패치에 대한 페이지로 이어질 :
-fconstexpr-steps
. 이 옵션을 검색하면 사용자 수준의 문서가 없음을 나타냅니다.
따라서 clang이 '단계'또는 얼마나 많은 '단계'clang이 fib(27)
에 필요한지에 대한 문서는 없습니다. 우리는 이것을 정말로 높게 설정할 수는 있지만 나쁜 생각이라고 생각합니다. 대신, 일부 실험은 보여
n : steps
0 : 2
1 : 2
2 : 6
3 : 10
4 : 18
나타내는 것을 단계 (fib(n)
) == 단계 (fib(n-1)
) + 단계 (fib(n-2)
) + 2 계산 약간 이에 따라 fib(27)
는 연타 년대 1,271,242을 요구해야한다는 도시 단계. 따라서 -fconstexpr-steps=1271242
으로 컴파일하면 프로그램을 컴파일 할 수 있어야합니다. 실제로는 it does입니다.-fconstexpr-steps=1271241
으로 컴파일하면 이전과 동일한 오류가 발생하므로 정확한 제한이 있음을 알 수 있습니다.
덜 정확한 방법은 패치에서 기본 단계 제한이 1,048,576 (2) 인 것을 관찰하는 것입니다. 이는 분명히 fib(26)
으로 충분합니다. 직관적으로 배가는 충분해야하며 초기 분석에서 2 백만 명이 충분하다는 것을 알 수 있습니다. 단단한 한도는 ⌈φ · steps() ⌉이다 (정확하게 1,271,242).
또 다른 주목할 점은 이러한 결과가 clang이 constexpr 평가의 메모를 수행하지 않는다는 것을 분명히 보여줍니다. GCC does,하지만 이것은 clang에서 전혀 구현되지 않은 것처럼 보입니다. 메모 작성으로 인해 메모리 요구 사항이 늘어나더라도이 경우와 같이 평가에 소요되는 시간을 크게 줄일 수 있습니다. 필자가이 글에서 결론을 내린 두 가지 결론은 좋은 컴파일 시간을 위해 memoization을 요구하는 constexpr 코드를 작성하는 것이 이식 가능한 코드에는 좋지 않으며 constexpr memoization과 명령 행 옵션을 지원하여 clang을 향상/비활성화 할 수 있다는 점이다.
@ 브라이언 : 감사합니다. 어떻게 든 그것을 올바르게 포맷 할 수 없었습니다. – Sarang
흠, GCC가 잘 처리합니다 ... –
반면에 Clang은 전통적인 템플릿 스타일 메타 프로그램에 완벽하게 만족합니다. –