我想在 for 循环中迭代一些
std::vector
,但根据某些条件,向量应向前或向后迭代。我想,我可以通过使用普通迭代器或反向迭代器轻松地做到这一点,如下所示:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec{0, 1, 2, 3, 5, 6, 7};
bool reverse = true;
std::iterator<random_access_iterator_tag, int> it, end_it;
if (reverse) {
it = vec.rbegin();
end_it = vec.rend();
} else {
it = vec.begin();
end_it = vec.end();
}
for (; it != end_it; it++) {
cout << *it << ", ";
}
return 0;
}
但不幸的是
vector::begin()
和 vector::rbegin()
似乎没有使用相同的父类。有没有另一种方法可以做我想做的事情,而无需在 if-else 结构中使用两个不同的循环?当然,我可以为循环体创建一个函数/lambda 或使用一些索引算术,但有更优雅的方法吗?
编译器抱怨赋值
it = vec.begin()
,因为它们是不同的类型。 gcc 和 VC++ 输出不同的错误,并且似乎对 vector::begin
的返回值使用不同的类型。
编辑:链接的讨论/答案不是我需要的(编辑)。我不想将反向迭代器转换为正向迭代器,而是想将它们中的任何一个保存在同一变量中。或者更确切地说 - 正如 @Edgar Rokjān 所说 - 一种在任一方向上遍历容器的统一而优雅的方式。
有了新的
std::ranges
,它似乎也没有那么容易工作。例如,
auto transformed =
reverse ? vec | std::ranges::views::all : vec | std::ranges::views::reverse;
导致类似的错误
operands to '?:' have different types 'std::ranges::ref_view<std::vector<int> >' and 'std::ranges::reverse_view<std::ranges::ref_view<std::vector<int> > >'
我想,最优雅的解决方案是将循环体扔进 lambda 中,然后在决定是否以相反的顺序进行遍历后使用它。那么我会提出一个包括这个在内的答案。
不确定是否更好,您会接受没有 std::iterator 的解决方案,但我认为这稍微更优雅:
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> vec{0, 1, 2, 3, 4, 5, 6};
bool reverse = true;
for(int i: vec){
if(reverse)
cout << vec[vec.size()-i] << endl;
else
cout << vec[i] << endl;
}
}
效率不是很高,因为你必须在每个循环中检查是否。