[英]Is there a way to set an offset to a range-based for loop in C++?
Suppose that these classes have an inner array of AnotherObjectClass type that can be accessed through a function called GetAnotherObjectClassTerms.假设这些类有一个可以通过名为 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;
}
}
}
}
I can do this in a normal for loop by creating a variable that holds that last index, so that when it starts iterating, it starts from that specific position.我可以在普通的 for 循环中通过创建一个保存最后一个索引的变量来做到这一点,这样当它开始迭代时,它就会从那个特定位置开始。
The following code is to show my problem using a traditional for-loop as requested.以下代码是根据要求使用传统的 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++;
}
}
}
The output of the code above would be:上面代码的输出将是:
Output #1: 0 <= 0
Output #2: 1 > 0
Output #3: 2 > 0
Output #4: 1 <= 1
Output #5: 2 > 1
Output #6: 2 <= 2
As you can see, the inner loop doesn't iterate from the "beginning" whenever the variable temp is incremented.如您所见,只要变量 temp 增加,内循环就不会从“开始”开始迭代。
So my question is: can this be done in a range-based for loop?所以我的问题是:这可以在基于范围的 for 循环中完成吗? If so, how this offset can be applied to a range-base for loop?
如果是这样,如何将此偏移量应用于范围基础 for 循环? Or, should I completely avoid this and go with a normal for-loop?
或者,我应该完全避免这种情况并使用正常的 for 循环吗?
The real problem that I'm having is that I need the inner loop to start by an offset by +1 when the break statements is reached .我遇到的真正问题是,当到达 break 语句时,我需要内部循环以 +1 的偏移量开始。
Take into account that the range-based for is looping through the elements of an array.考虑到基于范围的 for 循环遍历数组的元素。
If you can use Boost, you can use boost::adaptors::sliced
to get a slice of your range.如果您可以使用 Boost,则可以使用
boost::adaptors::sliced
来获取范围的一部分。 The following is a complete example:下面是一个完整的例子:
#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;
}
}
}
}
Output:输出:
Term 1 is not greater than term 2
Term 1 is not greater than term 2
Term 1 is not greater than term 2
You can also implement a simple class, say Offset
.你也可以实现一个简单的类,比如
Offset
。 When combined with a range, it returns a proxy class with begin()
and end()
member functions (so that it is able to behave like a range), say View
, which represents the offseted range.当与范围结合时,它返回一个代理类,其中包含
begin()
和end()
成员函数(以便它能够像范围一样工作),比如说View
,它表示偏移范围。
Example:示例:
#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.