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

问题描述 投票:0回答:1

考虑以下片段

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++ reference language-lawyer constexpr c++23
1个回答
4
投票

常量表达式中对未知数的指针和引用直接格式错误,可能会在 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,该工作组尚未考虑该问题。

© www.soinside.com 2019 - 2024. All rights reserved.