Below is a recursive lambda expression that can compute the values of Fibonacci sequence both in runtime and during constant evaluation:
auto fib = [](this auto && f, auto && p) {
if ( p < 3 ) return 1;
decltype(+p) v{};
v = p - 2;
return f(v+1) + f(v);
};
// ok everywhere
static_assert( fib(1) == 1 );
static_assert( fib(2) == 1 );
static_assert( fib(3) == 2 );
static_assert( fib(4) == 3 );
static_assert( fib(5) == 5 );
static_assert( fib(6) == 8 );
static_assert( fib(7) == 13 );
static_assert( 20 <= fib(8) && fib(8) <= 21 );
// fails in MSVC
static_assert( fib(8) == 21 );
As far as I can see it works fine in GCC and Clang, but in Visual Studio it is so only for the first 7 elements, and fib(8) is computed inaccurately resulting in a failure of static assertion. Online demo: https://gcc.godbolt.org/z/dMM6f16do
If the program is correct, why does it perform well for small numbers and does not work for larger ones (e.g. integer overflow, too many recursive calls)?
pis just declared as anint.fib(8)and agrees it's 21 as can be seen by modifying your example toreturn fib(8)(gcc.godbolt.org/z/6h7YThT7M)auto pis also ok for MSVC, so... I agree, this is a bug in MSVCconstexpr, it is possible you reach it for MSVC. (constexprdoesn't requires memoization).static_assertis particularly poor in that it gives literally no information whatsoever... but the problem is taht it thinksfib(8)is20, not that it cannot evaluatefib(8): gcc.godbolt.org/z/zqTn5Yv4K