[英]Is there a way to set an offset to a range-based for loop in C++?
假设这些类有一个可以通过名为 GetAnotherObjectClassTerms 的函数访问的 AnotherObjectClass 类型的内部数组。
#include<iostream>
int main() {
// Suppose a default constructor that assigns values to the arrays
AnObjectClass obj1;
AnObjectClass obj2;
for (AnotherObjectClass term1 : obj1.GetAnotherObjectClassTerms) {
for (AnotherObejctClass term2 : obj2.GetAnotherObjectClassTerms) {
if (term1 > term2) {
std::cout << "Term 1 is greater than term 2" << std::endl;
} else {
std::cout << "Term 1 is not greater than term 2" << std::endl;
// OFFSET THIS INNER LOOP so it doesn't iterate through all the items again.
break;
}
}
}
}
我可以在普通的 for 循环中通过创建一个保存最后一个索引的变量来做到这一点,这样当它开始迭代时,它就会从那个特定位置开始。
以下代码是根据要求使用传统的 for 循环来显示我的问题。
for (unsigned short i = 0, temp = 0; i < 3; i++) {
for (unsigned short j = temp; j < 3; j++) {
// This traditional for-loop iterates through a different range
// whenever the 'temp' value is increased
if (j > i) {
std::cout << j << " > " << i << std::endl;
}
else {
std::cout << j << " <= " << i << std::endl;
temp++;
}
}
}
上面代码的输出将是:
Output #1: 0 <= 0
Output #2: 1 > 0
Output #3: 2 > 0
Output #4: 1 <= 1
Output #5: 2 > 1
Output #6: 2 <= 2
如您所见,只要变量 temp 增加,内循环就不会从“开始”开始迭代。
所以我的问题是:这可以在基于范围的 for 循环中完成吗? 如果是这样,如何将此偏移量应用于范围基础 for 循环? 或者,我应该完全避免这种情况并使用正常的 for 循环吗?
我遇到的真正问题是,当到达 break 语句时,我需要内部循环以 +1 的偏移量开始。
考虑到基于范围的 for 循环遍历数组的元素。
如果您可以使用 Boost,则可以使用boost::adaptors::sliced
来获取范围的一部分。 下面是一个完整的例子:
#include <cstddef> // std::size_t
#include <iostream>
#include <iterator>
#include <boost/range/adaptor/sliced.hpp>
int main() {
int a[] = {0,1,2}, b[] = {0,1,2};
std::size_t off = 0;
for (int term1 : a) {
for (int term2 : b | boost::adaptors::sliced(off, std::size(b))) {
// ^^^^^^^^^ C++17 feature
if (term1 > term2) {
std::cout << "Term 1 is greater than term 2" << std::endl;
} else {
std::cout << "Term 1 is not greater than term 2" << std::endl;
++off;
break;
}
}
}
}
输出:
Term 1 is not greater than term 2
Term 1 is not greater than term 2
Term 1 is not greater than term 2
你也可以实现一个简单的类,比如Offset
。 当与范围结合时,它返回一个代理类,其中包含begin()
和end()
成员函数(以便它能够像范围一样工作),比如说View
,它表示偏移范围。
示例:
#include <cstddef> // std::size_t
#include <iostream>
#include <iterator>
#include <utility>
struct Offset {
std::size_t _offset;
};
constexpr Offset offset(std::size_t s)
{
return {s};
}
template <typename Iterator>
struct View {
constexpr Iterator begin() const {return _begin;}
constexpr Iterator end() const {return _end;}
Iterator _begin;
Iterator _end;
};
// Combine a range with an Offset using operator| like boost::adaptors::sliced
template <typename Range>
auto operator |(Range &&range, const Offset &offset)
-> View<decltype(std::begin(std::forward<Range>(range)))>
{
return {
std::begin(std::forward<Range>(range)) + offset._offset,
std::end(std::forward<Range>(range))
};
}
int main() {
int a[] = {0,1,2}, b[] = {0,1,2};
std::size_t off = 0;
for (int term1 : a) {
for (int term2 : b | offset(off)) {
if (term1 > term2) {
std::cout << "Term 1 is greater than term 2" << std::endl;
} else {
std::cout << "Term 1 is not greater than term 2" << std::endl;
++off;
break;
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.