2

I am trying to understand how constexpr works. I am initializing a constexpr variable from the return value of a constexpr function as in the below code.

#include <iostream> using namespace std; constexpr size_t n = 40; constexpr size_t Fib(const size_t n) { if (n <= 1) return n; return Fib(n - 1) + Fib(n - 2); } int main() { //constexpr size_t Value = Fib(n); // ----> Line 1 const size_t Value = Fib(n); // ----> Line 2 cout << Value; } 

Line 1, if uncommented complains saying expression did not evaluate to a constant. However Line 2 works fine. What am I missing here?

3
  • 3
    I get a different error for Line 1. " evaluation operation count exceeds limit of 33554432". It seems like the compiler bails out because the computation is too long. What compiler are you using? Maybe it is getting the same problem and deciding that Fib can't be evaluated at compile time. See godbolt.org/z/f9fo3fb1f Commented May 22, 2021 at 13:33
  • 1
    I get a similar error message as @FrançoisAndrieux: "failure was caused by evaluation exceeding step limit of 1048576". Without memoizing it takes surprisingly many recursive calls to evaluate Fib(n)--exponentially many in n, in fact. The compiler is only willing to go so far in evaluating constexpr functions. Commented May 22, 2021 at 13:36
  • Suggested alternative implementation: Instead of recursion, use iteration. A for loop that runs n times, computing one additional value in the sequence each time. O(n) time, O(1) additional storage, very constexpr-friendly. (Strictly speaking there's an O(1)/O(1) algorithm but dealing with floating point imprecision is probably more of a headache than living with O(n) for very small n. You overflow a size_t before n=100.) Commented May 22, 2021 at 13:59

1 Answer 1

2

constexpr tells the compiler that it can be resolved at compile time, but does not guarantee it.

In Line 1, the compiler tries to resolve it at compile time. But the input is too large that the compiler fails to resolve it. The compiler output tells the full story.

# MSVC > error C2131: expression did not evaluate to a constant > message : failure was caused by evaluation exceeding step limit of 1048576 (/constexpr:steps<NUMBER>) 

But in Line 2, the value does not need to be resolved at compile time, the compiler can let the CPU handle it at runtime. This is why Line 2 works without a hickup.

To further prove the point, try reducing the input value from 40, to something like 10. The compiler will resolve it without an issue.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.