【发布时间】:2019-07-17 22:21:30
【问题描述】:
假设我们有一个普通数组(或其他支持基于范围的循环的容器):
const int N = 8;
int arr[N] = {0, 1, 2, 3, 4, 5, 6, 7};
使用索引或迭代器,我们可以遍历奇数元素并将索引增加 2:
for (int i = 0; i < N; i+=2)
{
std::cout << arr[i] << std::endl;
}
如何通过使用基于范围的循环并避免显式迭代器/索引和迭代跳过来获得类似的结果?像这样的:
for (const auto& v: odd_only(arr))
{
std::cout << v << std::endl;
}
简单而优雅的解决方案是什么样的?标准库是否包含这样的内容?
【问题讨论】:
-
我认为我们目前在 STL 中没有类似的东西,但 range-v3 的
view::stride可能是您正在寻找的东西(尽管我不确定它是如何工作的使用普通数组 -std::array应该没问题)。 -
更新:绝对适用于普通数组 (example)。
-
如前所述,没有直接支持。如果您不想在 3rd-party 库上进行中继,您可以做的只是类似于
bool isEven = false /* isOdd = true */; for(...) { if((isEven = !isEven)) { ... }; }。不过,我个人宁愿只保留原始循环... -
请注意,您的基于索引的示例使用
<。迭代器并不总是有<,而且更成问题的是,在末尾创建迭代器通常是未定义的行为,因此唯一的选择是单步执行并将每个迭代器与末尾进行比较(但仅在每隔一次迭代)。因此将进行迭代跳过,即使它对您隐藏。如果您不喜欢迭代跳过,则不能使用迭代器。 -
@Aconcagua:正确,
distance(it, e) < n(或e - it < n)可以在没有未定义行为的情况下完成,而不是直接转换索引 for 循环。可能应该有一些advance_not_past(it, n, e)函数对随机访问迭代器很有效,对其他迭代器仍然是最佳的(单次通过)。
标签: c++ c++11 range containers range-based-loop