Igo*_* R. 5 c++ reference language-lawyer constexpr c++20
考虑以下代码片段:
struct test1 {
static constexpr int get() {
return 1;
}
};
struct test2 {
constexpr int get() const {
return 1;
}
};
template <class T>
int get(T&& t) {
if constexpr (t.get() == 1) {
return 1;
}
return 2;
}
int main() {
return get(test1{}) + get(test2{});
}
Run Code Online (Sandbox Code Playgroud)
当尝试使用 GCC-11.1 (-std=c++2a) 进行编译时,get模板可以成功编译test1,但不能使用test2. 它们之间唯一的区别是test2::get是静态的。
显然,它不能用 进行编译test2,因为t参数不是“核心常量表达式”,根据7.7 expr.const(5.13):
表达式 e 是核心常量表达式,除非对 e 的求值遵循抽象机的规则,将求值以下表达式之一:
- 引用引用类型的变量或数据成员的 id 表达式,除非引用具有前面的初始化...
问题是,当通过同一引用访问的函数是静态的时,为什么它会编译。在这种情况下,参考文献不是被“评估”了吗?这是 GCC 错误还是标准中的某些措辞允许这样做?
常量表达式中对未知数的指针和引用直接格式错误可能会在 C++23 中得到解决,如果是这样,则作为早期语言版本的缺陷报告。
\n\n\n[...]当通过同一引用访问的函数是静态的时。在这种情况下,引用不是被“评估”了吗?这是 GCC 错误还是标准中的某些措辞允许这样做?
\n
对于这种情况,您的程序也是不正确的static,正如以下问答中详细回答的那样:
然而,EWG 认为这是 constexpr 规范中的缺陷,并建议 CWG 考虑通过P2280R3(在常量表达式中使用未知指针和引用)解决该问题,针对 C++23,并作为 C 的 DR(缺陷报告) ++11 到 C++20。
\n\n\njfbastien 于 2021 年 2 月 3 日发表评论
\nEWG 在今天的电视节目中看到了这篇论文。
\nP2280 在常量表达式中使用未知引用
\nP2280 中提出的用例是 constexpr 的 C++\xe2\x80\x99s 规范中的问题,我们希望修复这些问题,最好是在 C++23 中。
\n这应该是针对 C++20、C++17、C++14 和 C++11 的缺陷报告。
\n
CWG 同意,P2280 现已被 C++23 接受并作为缺陷报告。
\n