【问题标题】:Reference evaluation and constant expression引用求值和常量表达式
【发布时间】:2022-01-12 19:18:22
【问题描述】:

考虑following snippet

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)
  • 我认为是stackoverflow.com/q/44995196/817643 的骗子
  • @StoryTeller-UnslanderMonica 很酷,谢谢!所以这是 GCC 中的一个错误。
  • @StoryTeller-UnslanderMonica 这已通过P2280R3aimed for C++23 标记为 C++11 到 C++20 的未来 DR。
  • @dfrib - 被标记和通过有很大的区别。小心你的回答不要做出空洞的承诺。

标签: c++ language-lawyer constexpr


【解决方案1】:

直接不正确的常量表达式中的指针和对未知数的引用可能在 C++23 中得到解决,如果是这样,作为早期语言版本的缺陷报告。


[...] 当通过相同引用访问的函数是静态的时。在这种情况下,引用不是“评估”的吗?是 GCC 错误还是标准中的某些措辞允许?

对于static 的情况,您的程序也是不正确的,下面的问答中有详细回答:

然而,EWG 认为这是 constexpr 规范中的一个缺陷,并建议 CWG 考虑通过 P2280R3 解决它(在常量表达式中使用未知指针和引用),针对 C+ +23,并作为 C++11 到 C++20 的 DR(缺陷报告)。

jfbastien 于 2021 年 2 月 3 日发表评论

EWG 在今天的电话会议上看到了这篇论文。

P2280 在常量表达式中使用未知引用

P2280 中提出的用例是 C++ 的 constexpr 规范中的问题,我们希望在 C++23 中修复这些问题。

这应该是针对 C++20、C++17、C++14 和 C++11 的缺陷报告。

然而,最终决定权在于 CWG,它尚未研究该问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    • 1970-01-01
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多