考虑以下片段:
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{});
}
尝试使用 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 中得到解决,如果是这样,则作为早期语言版本的缺陷报告。
[...] 当通过同一引用访问的函数是静态的时。在这种情况下,参考文献不是被“评估”了吗?这是 GCC 错误还是标准中的某些措辞允许这样做?
对于
static
的情况,您的程序也是格式错误的,如以下问答中详细回答的:
但是,EWG 认为这是 constexpr 规范中的缺陷,并建议 CWG 考虑通过P2280R3(在常量表达式中使用未知指针和引用)解决该问题,目标是 C++23,并作为 DR (缺陷报告)适用于 C++11 到 C++20。
jfbastien于2021年2月3日发表评论
EWG 在今天的电视节目中看到了这篇论文。
P2280 在常量表达式中使用未知引用
P2280 中提出的用例是 C++ constexpr 规范中的问题,我们希望修复这些问题,最好是在 C++23 中。
这应该是针对 C++20、C++17、C++14 和 C++11 的缺陷报告。
最终决定权在于 CWG,该工作组尚未考虑该问题。