2012-02-06 54 views
1

我試過寫一個通用的,到位的,intersperse函數。函數應該將給定的元素散佈到一系列元素中。std :: insert_iterator和迭代器失效

#include <vector> 
#include <list> 
#include <algorithm> 
#include <iostream> 

template<typename ForwardIterator, typename InserterFunc> 
void intersperse(ForwardIterator begin, ForwardIterator end, InserterFunc ins, 
       // we cannot use rvalue references here, 
       // maybe taking by value and letting users feed in std::ref would be smarter 
       const ForwardIterator::value_type& elem) { 
    if(begin == end) return; 
    while(++begin != end) { 
    // bugfix would be something like: 
    // begin = (ins(begin) = elem); // insert_iterator is convertible to a normal iterator 
    // or 
    // begin = (ins(begin) = elem).iterator(); // get the iterator to the last inserted element 

    // begin now points to the inserted element and we need to 
    // increment the iterator once again, which is safe 
    // ++begin; 
    ins(begin) = elem; 
    } 
} 

int main() 
{ 
    typedef std::list<int> container; 
    // as expected tumbles, falls over and goes up in flames with: 
    // typedef std::vector<int> container; 
    typedef container::iterator iterator; 
    container v{1,2,3,4}; 

    intersperse(v.begin(), v.end(), 
       [&v](iterator it) { return std::inserter(v, it); }, 
       23); 
    for(auto x : v) 
    std::cout << x << std::endl; 
    return 0; 
} 

的例子僅適用於那些不壞的插入他們的 迭代器的容器。我應該簡單地擺脫迭代器,並接受一個容器作爲參數,或者我錯過了使這種用法成爲可能的東西 insert_iterator

回答

2

該示例僅適用於在插入時不會使迭代器無效的容器。

沒錯。

我應該簡單地擺脫了迭代器,並接受容器作爲參數

這將是一個可能性。另一個不會使算法就地(即輸出到不同的容器/輸出迭代器)。

我錯過了一些關於insert_iterator的東西,使這種用法成爲可能嗎?

編號insert_iterator意味着重複插入到容器的單個位置,例如,通過變換算法。

0

您的實施問題與insert_iterator的屬性完全無關。 C++標準庫中的所有類型的插入迭代器都保證有效,即使您插入容器時可能會導致插入時迭代器失效。當然,只有通過插入迭代器才能執行所有插入操作,情況纔是正確的。

換句話說,插入迭代器的實現保證了迭代器會自動「自愈」,即使插入導致容器中潛在的迭代器無效事件。

您的代碼存在的問題是beginend迭代器可能通過插入某些容器類型而失效。它是beginend,你需要擔心你的代碼,而不是插入迭代器。

同時,出於某種原因您完全倒退。你似乎在意刷新插入迭代器(這是完全不必要的),而完全忽略了beginend