为什么'constexpr const int &a = 1;'在块范围内失败了?
Why `constexpr const int &a = 1;` failed in block scope?
N4527 7.1.5[dcl.constexpr]p9
对象声明中使用的constexpr说明符将对象声明为const。这样的对象必须具有文字类型,并且必须初始化。如果由构造函数调用初始化,则该调用应为常量表达式(5.20)。否则,或者如果在引用声明中使用了constexpr说明符,则在其初始化项中出现的每个完整表达式都必须是常量表达式。
5.20 [expr.const] p5
一个常量表达式要么是一个glvalue核心常量表达式,其值指向一个实体一个常量表达式(定义如下)的允许结果,或者一个右值核心常量表达式,其Value是一个对象,对于该对象及其子对象:
—每个引用类型的非静态数据成员指向一个实体,该实体是常量表达式的允许结果,
—如果对象或子对象是指针类型,则它包含具有静态存储时间的对象的地址、该对象结束后的地址(5.7)、函数的地址或空指针值。
实体是常量表达式允许的结果,如果它是具有静态存储时间的对象,不是临时对象,或者是值满足上述约束的临时对象,或者是函数。
void foo(){
constexpr const int &a = 1;//error
constexpr static const int &b = 1;//ok in gcc 5.1.0 and clang 3.8.0
}
问题:为什么constexpr const int &a = 1;
在块范围内失败?
这在cwg缺陷报告2005:不正确的constexpr引用初始化需求中包含,该需求说(强调我的):
考虑如下示例:
constexpr int f() { return 5; } // function must be constexpr constexpr int && q = f(); // but result is not constant constexpr int const & r = 2; // temporary is still not constant int main() { q = 11; // OK const_cast< int & >( r ) = 3; // OK (temporary object is not ROMable) constexpr int && z = 7; // Error? Temporary does not have static storage duration? }
constexpr引用必须由常量表达式初始化(7.1.5 [dcl。[Constexpr]第9段),但它可以指可修改的临时对象。这样的临时保证是静态的初始化,但不是ROMable。
用左值表达式初始化的非const constexpr引用是有用的,因为它表明引用可能是静态初始化的,或者没有底层存储
当初始化式是临时类型时,查找其地址很简单。没有理由在其计算过程中声明任何意图地址。另一方面,提供了一个初始值,即也需要是一个常量表达式,尽管它从未被处理过作为常量
本地constexpr引用的情况更糟。初始化器在执行声明时生成临时对象。临时是局部作用域的唯一对象。这将呈现constexpr没有意义,因为虽然地址计算是微不足道的,它仍然必须动态完成。
c++ 11 constexpr引用需要按引用初始化常量表达式,它必须"用static来指定对象"函数的存储时间" (c++ 11 5.20 [expr。[参]第3段。由引用授予的具有自动存储期限的临时对象
c++ 14删除了引用常量表达式和静态存储需求,用明显定义好的程序呈现失败的constexpr说明符。(GCC和Clang目前提供c++ 11诊断。)
建议解析:临时绑定到constexpr引用应该本身是constexpr,暗示const限定类型。禁止将constexpr引用绑定到临时对象,除非两者都具有static存储时间。(在局部范围内,静态说明符修复问题好。)
回应是这已经被5.20
第4段禁止了:
这个问题已经在5.20 [expr]中提到了。第4段,其中包括分析中的转换和临时。
- 为什么在全局范围内使用"extern int a"似乎不行?
- 错误:未在此范围内声明'reverse'
- 并行用于C++17中数组索引范围内的循环
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 不计算一个范围内的完美数
- 错误:"imread"未在此范围内声明
- 我在范围内未声明的错误类有问题
- 如何在cpp中使用地图显示给定日期范围内(在下面的问题中)的费率?
- 我有一个数组,我想输入一个范围,然后找到范围内所有偶数的总和?
- 未在此范围内声明错误 'xy'
- 在C++中使用变量而不是"#define"来指定数组大小是不是一种糟糕的做法?(C错误:在文件范围内
- 命名空间范围内的外部 - GCC vs clang vs msvc
- 如何改进一堆在已知值范围内评估变量的 else-if 条件?
- 如何仅使用 While 循环在给定范围内找到可被 7 整除的计数整数
- Socklen_t未在此范围内声明
- 错误:'[' 之前预期的非限定 id 和错误:'users'未在此范围内声明
- 查找给定范围内最长连续 1 的频率
- "Main"已在当前范围内声明
- 为什么 is_default_constructible<Class>::value 在同一类范围内失败
- 为什么'constexpr const int &a = 1;'在块范围内失败了?