2012-02-06 77 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