下面是一个递归 lambda 表达式,可以在运行时和持续求值期间计算 斐波那契序列 的值:
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 );
据我所知,它在 GCC 和 Clang 中运行良好,但在 Visual Studio 中仅适用于前 7 个元素,并且
fib(8)
计算不准确,导致静态断言失败。在线演示:https://gcc.godbolt.org/z/dMM6f16do
如果程序是正确的,为什么它对于较小的数字表现良好,而对于较大的数字则不起作用(例如整数溢出、太多的递归调用)?
这绝对是一个 msvc bug。请注意,当我们编写以下内容时,msvc 会打印
21
:
int main()
{
std::cout << fib(8) << "\n"; //msvc prints 21
constexpr int i = fib(8);
std::cout << i; //msvc prints 20
}