简体   繁体   English

从整数索引for循环枚举到range-for

[英]From integer-indexed for loop enumeration to range-for

I have some code that enumerates some data, something like this: 我有一些代码列举了一些数据,如下所示:

int count;
InitDataEnumeration(/* some init params */, &count);

for (int i = 0; i < count; i++) 
{ 
    EnumGetData(i, &data);
    // process data ...
}

I'd like to convert this code in a form suitable to C++11's range-for . 我想以适合C ++ 11 范围的形式转换此代码。

I was thinking of defining a DataEnumerator wrapper class, whose constructor would call the above InitDataEnumeration() function. 我在考虑定义一个DataEnumerator包装类,其构造函数将调用上面的InitDataEnumeration()函数。

The idea would be to use this wrapper class like this: 想法是使用这样的包装类:

DataEnumerator enumerator{/* init params*/};

for (const auto& data : enumerator) 
{
    // process data ...
}

How could the former int -indexed for loop be refactored in the latter range-based form? 如何在后一个基于范围的形式中重构前一个int -indexed for循环?

I was thinking of exposing begin() and end() methods from the enumerator wrapper class, but I don't know what kind of iterators they should return, and how to define such iterators. 我正在考虑从枚举器包装类中公开begin()end()方法,但我不知道它们应该返回什么类型的迭代器,以及如何定义这样的迭代器。

Note that the iteration process is forward-only. 请注意,迭代过程仅向前。

What you are looking for can be done with boost::irange . 您正在寻找的是可以使用boost::irange It will construct a lazy range of integers in the range [first, last) and you can just drop it right in like you use i in your for loop. 它将在[first, last)范围内构造一个惰性的整数范围,你可以像在for循环中一样使用i来直接删除它。

for (int i = 0; i < count; i++) 
{ 
    EnumGetData(i, &data);
    // process data ...
}

Becomes

for (auto i : boost::irange(0, count))
{
    EnumGetData(i, &data);
    // process data ...
}

You require an input iterator this example completely copied from http://en.cppreference.com/w/cpp/iterator/iterator : 您需要一个输入迭代器,此示例完全从http://en.cppreference.com/w/cpp/iterator/iterator复制:

 #include <iostream> #include <algorithm> template<long FROM, long TO> class Range { public: // member typedefs provided through inheriting from std::iterator class iterator: public std::iterator< std::input_iterator_tag, // iterator_category long, // value_type long, // difference_type const long*, // pointer long // reference >{ long num = FROM; public: explicit iterator(long _num = 0) : num(_num) {} iterator& operator++() {num = TO >= FROM ? num + 1: num - 1; return *this;} iterator operator++(int) {iterator retval = *this; ++(*this); return retval;} bool operator==(iterator other) const {return num == other.num;} bool operator!=(iterator other) const {return !(*this == other);} reference operator*() const {return num;} }; iterator begin() {return iterator(FROM);} iterator end() {return iterator(TO >= FROM? TO+1 : TO-1);} }; int main() { // std::find requires a input iterator auto range = Range<15, 25>(); auto itr = std::find(range.begin(), range.end(), 18); std::cout << *itr << '\\n'; // 18 // Range::iterator also satisfies range-based for requirements for(long l : Range<3, 5>()) { std::cout << l << ' '; // 3 4 5 } std::cout << '\\n'; } 

You are right about begin() and end() , whatever they return should supply: 你对begin()end()看法是正确的,无论它们返回应该提供什么:

  • operator++ (prefix only is enough) operator ++(仅前缀就足够了)
  • operator!= 运算符!=
  • operator* 运营商*

All pretty self-explanatory. 一切都不言自明。

Notice that no traits or categories are required, as would be for iterators intended for some standard library algorithms - just bare minimum. 请注意,不需要任何特征或类别,就像用于某些标准库算法的迭代器一样 - 只是最低限度。

for(auto x : y) Here, y must be an object of a class that has a begin() method and an end() method that each returns an object implementing the concept of an iterator. for(auto x : y)这里, y必须是一个类的对象,该类具有begin()方法和end()方法,每个方法都返回一个实现迭代器概念的对象。 The iterator must be incrementable ( iter++ ), must be able to accurately determine if it is equal to another iterator of the same kind (via != ) and must de-reference to whatever x needs to be. 迭代器必须是可递增的( iter++ ),必须能够准确地确定它是否等于同一类型的另一个迭代器(通过!= ),并且必须取消引用任何需要的x

This is something you should consider doing if you either A) are bored or otherwise have nothing better to do or B) have a legit need to. 如果您要么A)感到无聊或者没有其他更好的事情要做,或者B)有合法需要,那么您应该考虑这样做。 While this is not difficult to do, neither is it trivial. 虽然这不难做到,但也不是微不足道的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM