【发布时间】:2021-12-27 10:41:55
【问题描述】:
我试图找出 cpp11/14 中 constexpr 的限制。我在 CPP14-5.19-4 中找到了一些使用要求:
常量表达式要么是泛左值核心常量表达式 其值是指具有静态存储持续时间的对象或 函数或纯右值核心常量表达式,其值为 对象位置,对于该对象及其子对象:
- ...
- 如果对象或子对象是指针类型,则包含另一个具有静态存储期限的对象的地址,地址过去 这样一个对象的结尾(5.7),一个函数的地址,或者 空指针值。
我已经对涉及地址运算符& 的表达式进行了一些测试(代码如下),以确保上面引用的标准语句的正确性。
简单地说,我试图获取一个全局int变量global_var的地址,这是一个具有静态存储持续时间的对象(如果我没有想错的话),一切正常,正如标准所指出的那样。但是,让我感到困惑的是,当我尝试分配另一个指针类型对象(代码中的global_var_addr1)时,该对象存储了同一对象global_var 的地址,程序将无法编译。 GCC 说:
错误:“global_var_addr1”的值在常量表达式中不可用
注意:“global_var_addr1”未声明为“constexpr”
,而 Clang-Tidy 说:
错误:constexpr 变量“x2”必须由常量表达式初始化 [clang-diagnostic-error]
注意:常量表达式中不允许读取非 constexpr 变量“global_var_addr1”
我不知道为什么,我错过了什么吗?
所以我的问题是:
1.为什么,在常量表达式中,我不能使用包含具有静态存储持续时间的对象的地址的指针类型对象,正如标准所说的那样?
2.当指定对象为auto 时,为什么在与 (1) 相同的上下文中一切都不同?
欢迎任何建议,提前谢谢!
代码:
const int global_var_c = 123;
int global_var = 123;
const void *global_var_addr1 = &global_var;
const void *global_var_addr2 = nullptr;
auto global_var_addr3 = nullptr;
auto main() -> int
{
constexpr const int x00 = global_var_c; // OK
constexpr const void *x0 = &global_var; // OK
// Operate on the object of pointer type
constexpr const void *x1 = &global_var_addr1; // OK
constexpr const void *x2 = global_var_addr1; // ERROR: read of non-constexpr variable 'global_var_addr1'...
// Operate on nullptr
constexpr const void *x3 = &global_var_addr2; // OK
constexpr const void *x4 = global_var_addr2; // ERROR: read of non-constexpr variable 'global_var_addr2'...
// Operate on nullptr (with type deduction)
constexpr const void *x5 = global_var_addr3; // OK
constexpr const void *x6 = &global_var_addr3; // OK
}
【问题讨论】:
标签: c++ language-lawyer constexpr constant-expression