5

I am using constexpr to get the Fibonacci number

Enumeration is used to calculate the fibonacci in compile time

#include <iostream>

constexpr long fibonacci(long long  n)
{
    return n < 1 ? -1 :
        (n == 1 || n == 2 ? 1 : fibonacci(n - 1) + fibonacci(n - 2));
}

enum Fibonacci
{
    Ninth =    fibonacci(9),
    Tenth =    fibonacci(10),
    Thirtytwo = fibonacci(32)

};

int main()
{
    std::cout << Fibonacci(Thirtytwo);
   // std::cout << fibonacci(32);
    return 0;
}

I am getting the following error on execution:

1>c:\users\hsingh\documents\visual studio 2017\projects\consoleapplication4\consoleapplication4\source.cpp(12): note: while evaluating 'fibonacci(30)'
1>c:\users\hsingh\documents\visual studio 2017\projects\consoleapplication4\consoleapplication4\source.cpp(6): note: while evaluating 'fibonacci(31)'
1>c:\users\hsingh\documents\visual studio 2017\projects\consoleapplication4\consoleapplication4\source.cpp(12): note: while evaluating 'fibonacci(31)'
1>c:\users\hsingh\documents\visual studio 2017\projects\consoleapplication4\consoleapplication4\source.cpp(12): error C2131: expression did not evaluate to a constant
1>c:\users\hsingh\documents\visual studio 2017\projects\consoleapplication4\consoleapplication4\source.cpp(5): note: failure was caused by control reaching the end of a constexpr function
1>c:\users\hsingh\documents\visual studio 2017\projects\consoleapplication4\consoleapplication4\source.cpp(12): note: while evaluating 'fibonacci(32)'
1>c:\users\hsingh\documents\visual studio 2017\projects\consoleapplication4\consoleapplication4\source.cpp(14): error C2057: expected constant expression
1>Done building project "ConsoleApplication4.vcxproj" -- FAILED.

But when I use run time int x=30, y=2; std::cout << fibonacci(x+y);//fibonacci is calculated on run time

Run Time with memory

I won't say I have a question but I have few confusions like:

  1. Is memory used by compile time and run time use of constexpr different?
  2. How do I know where to stop exploiting or using compile time data?
  3. Which I am still trying to do is how to do Fibo-like calculation using both the advantage of compile time and run time together (use compile till it can be and after that let rest of calculation be done on run time).

Any example or reference if available will be helpful.

Hariom Singh
  • 3,512
  • 6
  • 28
  • 52
  • what do you mean with "when I use run time" ? Isnt that exactly the same code (minus two lines) ? – 463035818_is_not_an_ai Aug 10 '17 at 14:30
  • std::cout << fibonacci(32); Its a run time calculation – Hariom Singh Aug 10 '17 at 14:31
  • May or may not be a duplicate of [When does a constexpr function get evaluated at compile time?](https://stackoverflow.com/q/14248235/11683) – GSerg Aug 10 '17 at 14:36
  • 4
    I don't think `std::cout << fibonacci(32);` [is evaluated at runtime](https://godbolt.org/g/NK6ou9) unless optimizations are disabled. – MB-F Aug 10 '17 at 14:37
  • 1
    @kazemakase presently based on memory trace I can say its done at run time – Hariom Singh Aug 10 '17 at 14:45
  • Possible duplicate of [When does a constexpr function get evaluated at compile time?](https://stackoverflow.com/questions/14248235/when-does-a-constexpr-function-get-evaluated-at-compile-time) – Jean-Baptiste Yunès Aug 10 '17 at 14:46
  • I was a bit confused about your premise that one is computed at compile time and the other at runtime. I think the only thing you can be certain about is that the call via the enum is computed at compile time, but the other may also happen at compile time – 463035818_is_not_an_ai Aug 10 '17 at 14:51
  • @ tobi303 Please do correct if anything is wrong in question – Hariom Singh Aug 10 '17 at 14:53
  • 1
    @Jean-BaptisteYunès, not really, OP has a bigger issue right now (albeit the bigger issue is arguably closeable as 'typo error') – SergeyA Aug 10 '17 at 14:54
  • The error doesn't show up with gcc. Only with clang. And only for numbers greater than 27. – Michaël Roy Aug 10 '17 at 15:25

2 Answers2

7
  1. Memory used by the constexpr function at compile time is implementation dependent, but in general should be comparable to runtime (most compilers will compile and execute the statement).

  2. In theory, you should use compile time evaluated expressions whenever possible. In practice, it's a judgment call (perhaps a good topic for an SE question), as the down sides are increased compile time (and perhaps memory) and lack of debugging.

  3. It appears you are reaching the maximum recursion limit allowed by MSVC in compile time expressions. I can't find any documentation on what this limit is, but it's configurable on other compilers. Your error is the result of the enum requiring it to be fully evaluated at compile time, where as the cout call allows it be executed at compile time and/or run time (if you generate assembly, you should see compile time constants generated for the lower number calls, and a recursive function being used for the high number calls).

dlasalle
  • 1,615
  • 3
  • 19
  • 25
2

The reason for error is that you are trying to calculate Fib number of Fib number of 32. This is way to much!

You hit the maximum limit of constexpr function recursion, and thus you see a compilation error.

At runtime your program would crash at this point, but it doesn't, because your run-time expression is different - it is a Fib of 32.

SergeyA
  • 61,605
  • 5
  • 78
  • 137