这是我的代码:
class agg_t1{
int x; // private non-static data menber
};
class agg_t2{
agg_t2(){} // user-provided constructor
};
constexpr void ce1(agg_t1 arg){}; // OK
constexpr void ce2(agg_t2 arg){}; // ERROR: parameter type 'agg_t2' is not a literal type
Run Code Online (Sandbox Code Playgroud)
constexpr 函数的定义应满足以下要求: ...
- 它的每个参数类型都应该是文字类型;...
如果类型是文字类型,则它是: ...
- 它可以是闭包类型、聚合类型,或者......
我理解为什么agg_t2不是文字类型的原因是,它违反了规则dcl.init.aggr#1.1:
聚合是一个数组或一个类......
- 没有用户声明或继承的构造函数...
我认为agg_t1可能不是文字类型,因为它也违反了规则dcl.init.aggr#1.1:
聚合是一个数组或一个类......
- 没有私有或受保护的直接非静态数据成员...
然而......编译器结果告诉我我对 的假设是错误的agg_t1。
如果agg_t1的私有数据成员x …
c++ language-lawyer constant-expression constexpr constexpr-function
我试图找出限制constexprcpp11/14 中的限制。我在CPP14-5.19-4中发现了一些使用要求:
\n\n常量表达式可以是泛左值核心常量表达式\n其值引用具有静态存储持续时间的对象或函数\n,也可以是纯右值核心常量表达式\n其值是对象\n其中,对于该对象及其子对象:
\n\n
\n- ...
\n- 如果对象或子对象是指针类型,则它包含具有静态存储持续时间的另一个对象的地址、此类对象末尾的地址 (5.7)、函数的地址或空指针值。
\n
我已经对涉及地址运算符的表达式运行了一些测试(代码如下所示)&,以确保上面引用的标准语句的正确性。
简而言之,我试图获取全局int变量的地址global_var,它是一个具有静态存储持续时间的对象(如果我没有想错的话),一切都按照标准指出的那样工作。但是,令我困惑的是,当我尝试分配另一个指针类型对象(global_var_addr1在代码中)时,它存储了同一对象的地址global_var时,程序将无法编译。海湾合作委员会说:
\n\n错误:\xe2\x80\x98global_var_addr1\xe2\x80\x99 的值在常量表达式中不可用
\n
\n注意:\xe2\x80\x98global_var_addr1\xe2\x80\x99 未声明\xe2\x80\x98constexpr\xe2 \x80\x99
,而 Clang-Tidy 说:
\n\n\n错误:constexpr 变量“x2”必须由常量表达式初始化 [clang-diagnostic-error]
\n
\n注意:在常量表达式中不允许读取非 constexpr 变量 \'global_var_addr1\'
我不知道为什么,我错过了什么吗?
\n1. 为什么在常量表达式中,我不能使用标准规定的包含具有静态存储持续时间的对象的地址的指针类型对象?
\n 2. 为什么在与 (1) 相同的上下文中,当对象是auto?
欢迎任何建议,提前致谢!
\n代码:
\nconst …Run Code Online (Sandbox Code Playgroud) 我的程序(https://godbolt.org/z/Y93eG7K7s):
int main(){
int temp = 0;
int* tempp = &temp;
int** temppp = &tempp;
int*** tempppp = &temppp;
const int* intp0;
intp0 = tempp; // A
const int** intp1;
intp1 = temppp; // B
}
Run Code Online (Sandbox Code Playgroud)
GCC 或 Clang 都可以编译,但两者都会在B 行中引发相同的“不兼容指针类型”警告。我对这个警告没有问题,因为const int **和int **肯定是两个兼容的指针类型。然而(在我看来),const int *和int *也是两个兼容的指针类型(A 行)。
因此我的问题是:为什么const int *和int *被视为兼容的指针类型?