引用评估和常量表达式

Reference evaluation and constant expression

考虑 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):

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions:

  • an id-expression that refers to a variable or data member of reference type unless the reference has a preceding initialization...

问题是当通过同一个引用访问的函数是静态的时,为什么它会编译。在这种情况下,引用不是“评估”的吗?是 GCC 错误还是标准中的某些措辞允许它?

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


[...] when the function being accessed via the very same reference is static. Isn't the refence "evaluated" in this case? Is it a GCC bug or there's some wording in the Standard that allows it?

你的程序对于 static 的情况也是错误的,正如在下面的问答中详细回答的那样:

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

jfbastien commented on Feb 3, 2021

EWG saw this paper in today's telecon.

P2280 Using unknown references in constant expressions

The use cases presented in P2280 are problems in C++’s specification of constexpr, and we would like to fix these problems, ideally in C++23.

This should be a Defect Report against C++20, C++17, C++14, and C++11.

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