ranges::views 在编译时什么时候计算?

When are ranges::views calculated at compile time?

range-v3 library allows the use of views, which enable lazy operations on data. From what I know, lazy operations are only possible when a function is evaluated at compile time, but to achieve a compile time calculation, the code must be in a context where a constant expression是可以的。

我尝试使用函数 ranges::view::repeat_n(0,5) 重复数字并将其存储为 constexpr 变量,但编译器错误指出该函数不是 constexpr :

error: call to non-‘constexpr’ function ‘ranges::repeat_n_view<Val> ranges::views::repeat_n_fn::operator()(Val, std::ptrdiff_t) const requires  copy_constructible<Val> [with Val = int; std::ptrdiff_t = long int]’
   16 |     constexpr auto rng_view = ranges::view::repeat_n(0,5);

这是否意味着视图并不总是常量表达式?

这里是我的主要代码:

#include <iostream>
#include <string>
#include <range/v3/view/empty.hpp>
#include <range/v3/view/repeat_n.hpp>
#include <range/v3/algorithm/for_each.hpp>
#include <range/v3/view/cycle.hpp>
#include <range/v3/view/take.hpp>
using std::cout;

int main() {

    constexpr auto rng = ranges::view::empty<int>; //OK

    //repeat the number zero five times
    constexpr auto rng_view = ranges::view::repeat_n(0,5);//ERROR:Call to non-`constexpr` function
    std::cout << rng_view << std::endl;

    return 0;
{

是否有可能将所有 views 存储为 constexpr 值以确保编译时计算?

是的,视图并不总是常量表达式。有些(比如你发现的空的)可以声明为常量表达式。另一个 repeat_n() 的实现方式不允许它成为常量表达式。

但是,这只是回答了您的明确问题。更重要的是,您认为 "lazy operations are only possible when a function is evaluated at compile time" 的假设对我来说似乎是错误的,因此您的结论也随之而来。我不排除我们只是指不同的东西,所以也许你想澄清一下。

但是,对我来说,惰性求值只要求结果不依赖于任何外部状态,因此什么时候计算什么都无关紧要。在上面的例子中, repeat_n() 在实际使用它们之前不必生成值序列。这是一个糟糕的例子,因为任何理智的实现都不会生成超过一个值,但这不是重点。惰性求值中没有隐含的要求强制它成为一个常量表达式,也没有任何东西阻止它成为一个。

lazy operations are only possible when a function is evaluated at compile time

惰性操作是按需计算结果的操作,而不是在执行看似计算该结果的表达式时立即计算结果。例如,应用于某个容器的转换视图 出现 以立即将转换操作应用于视图的每个元素。但实际上,它仅在您尝试 访问 视图中的值时应用转换。

此过程与编译时执行无关。