关于 MSVC std::experimental::generator 中的暂停-恢复数据丢失

Hyd*_*gen 7 c++ generator c++-coroutine std-ranges c++23

自从std::generator正在进入 CPP23,我正在尝试 MSVC 的不完整版本。

然而,我注意到,yield与 一起使用时,它似乎恰好丢失了一个std::views::take。这是示例:

#include <iostream>
#include <ranges>

#include <experimental/generator>

std::experimental::generator<int> GeneratorFn(void) noexcept
{
    co_yield 1;
    co_yield 2;
    co_yield 3;
    co_yield 4;
    co_yield 5;
    co_yield 6;
    co_yield 7;
    co_yield 8;
    co_yield 9;
    co_return;
}

int main(int argc, char** args) noexcept
{
    auto Ret = GeneratorFn();
    for (auto&& i : Ret | std::views::take(2))
        std::cout << i << '\n';
    for (auto&& i : Ret | std::views::take(3))
        std::cout << i << '\n';
    for (auto&& i : Ret | std::views::take(4))
        std::cout << i << '\n';
}
Run Code Online (Sandbox Code Playgroud)

这段代码的输出将是

1
2
4
5
6
8
9
Run Code Online (Sandbox Code Playgroud)

显然,缺少了3和。7似乎std::views::take放弃了最后一个值generator

这在 C++23 正式版本中正常吗?
(在线尝试: https: //godbolt.org/z/v6MModvaz

康桓瑋*_*康桓瑋 9

std::generator是一个input_range,它begin()不保证平等:

auto Ret = GeneratorFn();
std::cout << *Ret.begin() << "\n"; // 1
std::cout << *Ret.begin() << "\n"; // 2
Run Code Online (Sandbox Code Playgroud)

当第一个 for 循环完成时,Ret的迭代器已经递增到值3。当您在第二个 for 循环中应用views::taketo时,这将再次调用s ,并且迭代器返回 by将是下一个值。RetRetbeginbegin4

如果您不想丢弃结束迭代器的值,可以像这样重用最后一个结束迭代器

auto Ret = GeneratorFn();
auto c = std::views::counted(Ret.begin(), 2);
for (auto i : c)
  std::cout << i << '\n';
for (auto i : std::views::counted(c.begin(), 3))
  std::cout << i << '\n';
for (auto i : std::views::counted(c.begin(), 4))
  std::cout << i << '\n';
Run Code Online (Sandbox Code Playgroud)

演示