2009-06-09 114 views
4

我有一個BOOST_FOREACH循環遍歷列表。不幸的是,我還需要將迭代器緩存到特定項目。在BOOST_FOREACH循環中訪問迭代器

typedef List::iterator savedIterator; 

BOOST_FOREACH(Item &item, list) 
{ 
// stuff... 
    if (condition) 
    savedIterator = &item; // this won't work 

// do more stuff...  
} 

很顯然,我可以做到這一點使用for循環list.begin().. list.end(),但我已經長大了喜歡BOOST_FOREACH。有沒有辦法解決這個問題?

回答

7

這是不可能的,因爲您無法訪問指向循環內的當前項的迭代器。

您可以使用當前項目數據以某種方式從列表中獲取迭代器,但我不知道這是否是一個好主意,也是性能明智之舉。

我建議你使用你已經用list.begin()。list.end()提出的解決方案,這在我看來是最容易實現和識別的。

4

隨着Boost.Foreach,你幾乎堅持引用迭代器的引用,因爲這是Boost.Foreach設計的目的:簡化對範圍內元素的訪問。但是,如果你只是想找一個適合一個標準的一個元素,你可能想嘗試std::find_if()

struct criteria { 
    template <class T> 
    bool operator()(T const & element) const { 
    return (element /* apply criteria... */)? true : false; 
    } 
}; 

// somewhere else 
List::iterator savedIterator = 
    std::find_if(list.begin(), list.end(), criteria()); 

它也像你想整個列表上的應用操作 - 在這種情況下,我我建議使用std::min_element()std::max_element()以及像boost::transform_iterator這樣的Boost.Iterators。

struct transformation { 
    typedef int result_type; 
    template <class T> 
    int operator()(T const & element) const { 
    // stuff 
    int result = 1; 
    if (condition) result = 0; 
    // more stuff 
    return result; 
    } 
}; 

// somewhere else 
List::iterator savedIterator = 
    std::min_element(
    boost::make_transform_iterator(list.begin(), transformation()), 
    boost::make_transform_iterator(list.end(), transformation()), 
).base(); 
+2

Upvoted,但僅僅是因爲它讓我想起了我是多麼討厭C++的時間。 – Roddy 2009-06-09 19:03:38

1

我有點納悶,爲什麼人們不這樣做:

#define foreach(iter_type, iter, collection) \ 
for (iter_type iter = collection.begin(); iter != collection.end(); ++iter) 
+1

如果`collection`是一個帶有副作用的表達式呢?你的宏將評估兩次。而且,傳統的`foreach`的重點是直接獲取值,而不會混淆迭代器(以及它們冗長笨拙的類型名稱)。 – 2009-12-07 08:03:10