为什么C++20范围适配器的返回视图不是一个常量表达式



考虑以下代码:

#include <ranges>
int main() {
constexpr int a[] = {1, 2, 3, 4};
constexpr auto r = a | std::views::take(3);
static_assert(*r.begin() == 1);
}

msvc接受它,gcc用拒绝它

<source>:5:44: error: 'std::ranges::take_view<std::ranges::ref_view<const int [4]> >{3, std::ranges::ref_view<const int [4]>{(& a)}}' is not a constant expression
5 |   constexpr auto r = a | std::views::take(3);
|                                            ^

为什么r不是一个常量表达式?

范围位是转移注意力。可以归结为这个

int main() {
constexpr int a[] = {1, 2, 3, 4};
constexpr auto r = a ;
}

我们不能形成指向a的第一个元素的constexpr指针。这样的指针被限制为仅保存具有静态存储持续时间的对象的地址。视图对象(作为其实现的一部分(将需要保留迭代器(在我们的例子中是指针(的副本。

由于r被声明为constexpr,并且它在内部保存一个指向对象的指针,所以该对象也必须具有静态存储持续时间。事实上,修改代码以包含

static constexpr int a[] = {1, 2, 3, 4};

让GCC愉快地接受你的榜样。

然而,MSVC不符合要求。它也接受无效的纯指针示例。

最新更新