为何consteval版RNG总是返回零?咨询C++标准对应条款
C++ consteval函数返回空指针的标准依据
在C++中,有一种实现随机数生成器(RNG)的方式是返回局部变量的地址:
void const* rng() noexcept { char c; return &c; }
这里利用每次函数调用时局部变量栈地址不同的特性,生成“随机”地址。
但尝试将其改为consteval变体时:
template <auto C> constexpr auto c() noexcept { return C; } consteval void const* rng() noexcept { char c; return &c; }
函数始终返回空指针。这种行为的依据可以在C++标准的常量表达式规则中找到:
核心标准条款依据
根据C标准的§7.7(常量表达式)章节(以C20为例):
- 常量表达式中,不能引用自动存储期对象的地址,除非该对象是用
constexpr声明且具备常量初始化,或是满足特定条件的临时对象。而consteval函数要求整个函数的求值结果必须是合法的常量表达式。
上述consteval版本的rng函数中,char c是函数内的局部自动变量,它的地址无法构成合法的常量表达式。编译器遇到这种违规情况时,会将该地址视为无效值,最终表现为返回空指针。
可编译变体的合理性
编辑2中的代码在Clang中可以正常编译:
template <auto C> constexpr auto c() noexcept { return C; } consteval auto rng1() noexcept { return &c<1>;} consteval auto rng2() noexcept { return &c<2>;}
原因是&c<1>获取的是模板函数实例化后的函数地址,而函数属于静态存储期实体,其地址是合法的常量表达式,符合标准中对常量表达式允许引用静态存储期实体地址的规定,因此可以在consteval函数中返回。
内容的提问来源于stack exchange,提问作者user1095108
相关产品推荐
相关产品推荐

