c++lambdaconstexprc++23explicit-object-parameter

Inaccurate compile-time computation of Fibonacci sequence in a recursive lambda


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)?


Solution

  • This is definitely a msvc bug(non-conformant behavior). Note that msvc prints 21 when we print fib(8) directly using std::cout:

    int main()
    {
        std::cout << fib(8) << "\n"; //msvc prints 21
        constexpr int i = fib(8);
        std::cout << i;              //msvc prints 20
    }
    

    Demo

    Here is the submitted bug report:

    MSVC prints different result based on call to constepxr function is used in constexpr context or not