为什么 `constexpr` 函数会在编译时和 运行 时产生不同的结果?
Why can a `constexpr` function produce different results at compile- and run-time?
我的一位同事向我展示了这个令人震惊的 C++20 程序:
#include <iostream>
constexpr int p(auto) { return 0; }
constexpr int q() { return p(0); }
constexpr int p(auto) requires true { return 1; }
static_assert(p(0) == 1);
static_assert(q() == 0);
int main()
{
std::cout << q() << p(0) << '\n';
}
由于错误,GCC 无法构建它:
Error: symbol `_Z1pIiEiT_' is already defined
Clang 成功构建程序并打印 11
( https://gcc.godbolt.org/z/1Gf5vj5oo )。所以 static_assert(q() == 0)
检查成功,但是 std::cout << q()
仍然打印 1
。怎么会这样?
Visual Studio 2019 16.10.4 表现得更奇怪了。在 Release 配置中它也打印 11
,而在 Debug 配置中它打印 00
。在这两种情况下,函数的 运行 时间值与其编译时值不同,由 static_assert
.
验证
我能想到的唯一解释是所有这些都是编译器错误,并且 constexpr
函数必须始终在编译时和 运行 时产生相同的结果。是吗?
虽然这个程序是人为设计的,但它 有效 并且按照您的想法行事(打印“01”),因此所有编译器都是错误的。 GCC 无法 mangle 将 requires true
转换为第二个 p
的名称,MSVC/Debug 无法 select more-constrained 重载,其他两种情况未能使用 lookup 结果来自 q
(它本身不是模板主题到多个实例化点)。
至于问题标题,std::is_constant_evaluated
允许 持续评估以产生与运行时评估不同的结果。只为善用这种力量!
我的一位同事向我展示了这个令人震惊的 C++20 程序:
#include <iostream>
constexpr int p(auto) { return 0; }
constexpr int q() { return p(0); }
constexpr int p(auto) requires true { return 1; }
static_assert(p(0) == 1);
static_assert(q() == 0);
int main()
{
std::cout << q() << p(0) << '\n';
}
由于错误,GCC 无法构建它:
Error: symbol `_Z1pIiEiT_' is already defined
Clang 成功构建程序并打印 11
( https://gcc.godbolt.org/z/1Gf5vj5oo )。所以 static_assert(q() == 0)
检查成功,但是 std::cout << q()
仍然打印 1
。怎么会这样?
Visual Studio 2019 16.10.4 表现得更奇怪了。在 Release 配置中它也打印 11
,而在 Debug 配置中它打印 00
。在这两种情况下,函数的 运行 时间值与其编译时值不同,由 static_assert
.
我能想到的唯一解释是所有这些都是编译器错误,并且 constexpr
函数必须始终在编译时和 运行 时产生相同的结果。是吗?
虽然这个程序是人为设计的,但它 有效 并且按照您的想法行事(打印“01”),因此所有编译器都是错误的。 GCC 无法 mangle 将 requires true
转换为第二个 p
的名称,MSVC/Debug 无法 select more-constrained 重载,其他两种情况未能使用 lookup 结果来自 q
(它本身不是模板主题到多个实例化点)。
至于问题标题,std::is_constant_evaluated
允许 持续评估以产生与运行时评估不同的结果。只为善用这种力量!