如何解决[expr.const]
constexpr int func(int const& rf){
return rf;
}
int main(){
constexpr int value = func(0);
}
考虑以上代码,变量value
将由常量表达式func(0)
初始化,该表达式首先应是核心常量表达式。为了确定表达式func(0)
是否为核心常量表达式,将应用以下规则,即:
expr.const#2.7
表达式e是核心常数表达式,除非按照抽象机的规则对e求值将对以下表达式之一求值:
从左值到右值的转换,除非将其应用于
[...]或
(2.7.4)文字类型的非易失性glvalue,指的是其寿命在e的求值内开始的非易失性对象;
尽管将lvalue-to-rvalue conversion
应用于rf
,并且这样的转换满足了项目符号(2.7.4)的要求,但是,请看下一段,即:
expr.const#2.11
引用引用类型的变量或数据成员的id表达式,除非引用具有之前的初始化且其中任何一个
- (2.11.1)使用常量表达式对其进行初始化,或者
- (2.11.2)其生存期始于e的评估;
我不知道短语preceding initialization
是什么意思?这是否意味着在使用变量之前应先对其进行初始化,还是意味着在变量的声明中应具有初始化程序。无论如何,在将lvalue-to-rvalue conversion
应用于glvalue rf
之前,应该对glvalue rf
进行评估以确定对象的身份,这取决于:
glvalue是一个表达式,其求值确定对象,位字段或函数的身份。
这意味着不仅要遵守子弹[expr.const#2.7],而且还要遵守[expr.const#2.11]。
因为id表达式rf
是引用类型。因此,为了使表达式func(0)
成为核心常量表达式,id表达式rf
必须具有之前的初始化,并且至少满足一个子弹(2.11 .1)和(2.11.2)。在我的示例中,rf
遵守项目符号(2.11.2),并且编译器同意func(0)
是一个常量表达式。结果为here,该结果似乎证明preceding initialization
的意思是be initialized
而不是初始化器,因为在第一个示例中,由于参数声明没有初始化器。
为了检查这种想法,我测试以下代码:
constexpr int func(int const& rf){
constexpr int const& v = rf;
return 0;
}
int main(){
static int const data = 0;
constexpr int value = func(data);
}
编译器的outcomes指出rf
不是常量表达式。我对这个结果感到困惑。根据以上假设。 rf
有一个先前的初始化,并且遵守(2.11.1)
是因为data
是一个常量表达式,即使不满足(2.11.2)
的情况。
所以,我想知道preceding initialization
这个词实际上是什么意思?如果这意味着变量的声明具有初始化程序,那么第一个示例中的表达式func(0)
怎么可能是常量表达式?
解决方法
结果似乎证明“在先初始化”的意思是“已初始化”,而不是因为参数声明而具有初始化器,因为第一个示例中没有参数初始化器。
它的确表示“已初始化”,但更重要的是,在要评估的表达式的上下文中,可见性是先前初始化的。在您的示例中,在评估func(0)
的上下文中,编译器具有查看rf
对0
的初始化的上下文。但是,在仅评估rf
中的表达式func
的情况下,看不到rf
的初始化。该分析是本地的,因为它不会分析每个呼叫站点。这会导致rf
中的表达式func
本身不是是常数表达式,而func(0)
是常数表达式。
如果要改写这个:
constexpr int func(int const& rf) {
/* constexpr */ int const& v = rf;
return v;
}
int main() {
static int const data = 0;
constexpr int value = func(data);
}
再次可以,因为在func(data)
的上下文中,rf
的初始化是带有常量表达式data
,而v
的初始化是带有{{ 1}},它不是一个常数表达式,但是其生存期始于rf
的求值。
这是CWG2186:
2186。不清楚“必须在初始化之前”
与问题2166相似,对8.20 [expr.const]项目符号2.7.1的要求
-整数或枚举类型的非易失性glvalue,它引用具有先前初始化,使用常量表达式初始化的完整非易失性const对象,或者
没有指定确定“在先初始化”的时间点:是在变量的引用按词法出现的那一点,还是在最外面的常量求值发生的那一点?在这一点上,实现上存在分歧。
但是含义应该是“词汇上的”,因为ODR。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。