【发布时间】:2022-01-12 19:18:22
【问题描述】:
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 错误还是标准中的某些措辞允许?
【问题讨论】:
-
Clang 不接受
get(test1) -
@StoryTeller-UnslanderMonica 很酷,谢谢!所以这是 GCC 中的一个错误。
-
@StoryTeller-UnslanderMonica 这已通过P2280R3、aimed for C++23 标记为 C++11 到 C++20 的未来 DR。
-
@dfrib - 被标记和通过有很大的区别。小心你的回答不要做出空洞的承诺。
标签: c++ language-lawyer constexpr