引用求值什么时候会使某些东西不是常量表达式?

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 错误还是标准中的某些措辞允许这样做?

dfr*_*fri 4

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

\n
\n
\n

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

\n
\n

对于这种情况,您的程序也是不正确的static,正如以下问答中详细回答的那样:

\n\n

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

\n
\n

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

\n

EWG 在今天的电视节目中看到了这篇论文。

\n

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

\n

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

\n

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

\n
\n

CWG 同意,P2280 现已被 C++23 接受并作为缺陷报告。

\n