tom*_*dol 3 c++ c++20 std-ranges
我一直在尝试一些只是为了好玩,但我偶然发现了以下方法的问题。问题是我在生成的范围内两次得到零值。我错过了什么?我没有正确使用范围还是与 unordered_set 有关?
auto rng =
std::views::iota(0) |
std::views::transform([](size_t){ return rand() % 26; }) |
std::views::filter([u = std::unordered_set<size_t>()](size_t i) mutable { return !u.emplace(i).second; }) |
std::views::take(15);
for (auto&& x : rng) {
std::cout << x << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
std::views::filter的谓词和std::views::transform变换函数必须是regular_invocable. 特别是,这要求它保持相等,这意味着可调用对象在被调用时不能被修改。
您的过滤器 lambda 不满足此要求,因为它使用相同的数字调用它两次可能会导致不同的结果(truethen false)。
您的转换函数也不会,因为它取决于 的全局状态rand。这可能就是为什么你两次得到相同的数字的原因:范围算法期望[](size_t){ return rand() % 26; }在给定相同的输入的情况下返回相同的内容,因此它被多次调用,它期望它们是相同的。operator++会调用它来获取一个号码来测试过滤器,但operator*会再次调用它并给你一个不同的号码。
您可以通过协程或使用自定义迭代器编写自定义范围来实现此目的。或者,如果您始终有固定的最大数量,则评论中建议的生成+随机播放算法将起作用。
| 归档时间: |
|
| 查看次数: |
93 次 |
| 最近记录: |