2014-04-04 44 views
0

點我有指針的std::vector<MyClass*> container一些類的對象,並想用在向量來迭代範圍爲基礎的循環,這樣有基於範圍for循環開始在矢量

for (MyClass *item : container) 
{ 
    // Do stuff, not changing the container 
} 

在這個循環內,我想再次遍歷容器,但是從容器中的下一個元素開始。我真的無法找到這樣做沒有迭代的方式,所以我的解決辦法是隻使用那些代替

for (auto item1 = container.begin(); item1 != container.end(); ++item1) 
{ 
    for (auto item2 = item1.next(); item2 != container.end(); ++item2) 
    { 
     // Do stuff, not changing the container 
    } 
} 

我的問題是:有沒有這樣做的任何方式,而不必訴諸於迭代器?我意識到基於範圍的循環只是語法上的糖,而且真的使用迭代器,但我喜歡我的語法糖!

+0

沒有迭代器,你不能這樣做。但是您可以避免放棄迭代整個集合的語法糖,請參閱[本答案](http://stackoverflow.com/a/14920606/2079303)。 – user2079303

+0

謝謝,看起來很有趣。 –

+0

@ user2079303添加它作爲答案,我會接受它。 –

回答

1

加我的意見是由OP要求一個答案。

你不能這樣做沒有迭代器。但是您可以避免放棄用於迭代整個集合的語法糖,請參閱this answer。我沒有測試過這個代碼,但是對這個答案的評論顯示boost :: counting_range可能更好。

0

循環範圍迭代容器中的所有元素。這意味着您可以將該循環更改爲:

for (auto item1 : container) 
{ 
    for (auto item2 = item1.next(); item2 != container.end(); ++item2) 
    { 
     // Do stuff, not changing the container 
    } 
} 

由於內循環不會迭代整個容器,因此必須使用normal循環。

+3

'item1'不是迭代器.. – ikh

+0

@ikh沒有人說'item1'是一個迭代器。它是容器中的一個元素的副本(它是'MyClass *')。因此,我不確定我是否理解你的評論。 –

+0

我在我的例子中使用的'next()'函數是'std :: next()','MyClass *'既不實現也不能實現它,因爲next()應該返回一個迭代器指針到容器中的下一個元素。容器中的對象不知道有關容器的任何信息,因此無法從中獲取迭代器。 –

2

(請注意下面的編輯)

的爲範圍的循環不會給你訪問到內部迭代器。一方面,這很好,因爲你不能搞砸它。另一方面,這可能是不好的,因爲你需要迭代器來知道你在容器中的位置。因此,我們不能使用for-range循環作爲外部循環,除非您使用線性內存佈局迭代某些內容,您可以將某個項目的地址作爲迭代器。

此外,標準庫還沒有達到以方便的方式處理範圍的任務。我使用一些實用程序從像iterator_range加速這個代碼片段:

using boost::make_iterator_range; 
using std::next; 
for (auto iter1 = container.begin(), ee = container.end(); iter1 != ee; ++iter1) { 
    auto& item1 = *iter1; 
    for (auto& item2 : make_iterator_range(next(iter1),ee)) { 
     // do something with item1 and item2 
    } 
} 

誠然,不是很漂亮。但是這給出了一種方法,給出一對迭代器如何使用for-range循環。基本上,範圍循環吃任何提供開始/結束功能的東西。 make_iterator_range包裝了一對迭代器並返回一些東西,它提供了開始/結束函數。

編輯:我最近得知boost::irange也可以產生迭代器序列(而不僅僅是數字序列)。考慮到這一點,看看這個程序:

#include <iostream> 
#include <vector> 
#include <boost/range/irange.hpp> 
#include <boost/range/iterator_range.hpp> 
#include <boost/range/adaptor/indexed.hpp> 

int main() 
{ 
    using std::vector; 
    using std::next; 
    using boost::irange; 
    using boost::make_iterator_range; 
    namespace ba = boost::adaptors; 

    vector<double> x {1.1, 2.2, 3.3, 4.4, 5.5, 6.6}; 

    for (auto iter1 : irange(begin(x),end(x))) { 
     auto& item1 = *iter1; 
     for (auto& item2 : make_iterator_range(next(iter1),end(x))) { 
      // do something with item1 and item2 
      std::cout << item1 << " < " << item2 << std::endl; 
     } 
    } 

    return 0; 
} 

我的C++ 0x模式與G ++ 4.6.3測試這和Boost 1.48和它的實際工作。

+0

很好的答案!雖然我並不喜歡Boost,但是希望這樣的東西能夠成爲C++。 –

1

您可以創建一個簡單的類,將訪問範圍:

#include <vector> 
#include <iostream> 

template<typename I> 
struct Sub { 
    I _begin; 
    I _end; 

    Sub(I b, I e): _begin(b), _end(e) {} 

    I begin() const { return _begin; } 
    I end() const { return _end; } 
}; 

template<typename I> 
Sub<I> sub(I b, I e) { return Sub<I>(b, e); } 

int main() { 
    std::vector<int> a{0,1,2,3,4,5,6,7,8,9}; 

    for (auto i: sub(a.begin() + 3, a.end() - 1)) { 
     std::cout << i << "\n"; 
    } 
} 

此代碼打印:

3 
4 
5 
6 
7 
8