下面是一个递归 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 的一个错误(不符合规范的行为)。请注意,当我们直接使用以下命令打印时,msvc会打印 :
21
fib(8)
std::cout
演示
以下是提交的错误报告:
MSVC 根据对 constexpr 上下文中是否使用 constepxr 函数的调用来打印不同的结果