我尝试编写一个通用的intersperse
函数。该函数应该将给定元素散布到一系列元素中。
#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
使这种用法成为可能吗?
答案 0 :(得分:2)
该示例仅适用于在插入时不会使其迭代器失效的容器。
完全。
我应该简单地删除迭代器并接受一个容器作为参数
那将是一种可能性。另一种方法是不在适当的位置制作算法(即输出到不同的容器/输出迭代器)。
我是否遗漏了有关insert_iterator的内容,使这种用法成为可能?
没有。 insert_iterator
用于重复插入容器的单个位置,例如。通过变换算法。
答案 1 :(得分:0)
您的实施问题与insert_iterator
的属性完全无关。 C ++标准库中的所有类型的插入迭代器都保证保持有效,即使您执行插入到可能使插入上的迭代器无效的容器中也是如此。当然,只有通过插入迭代器执行所有插入时,这才是真的。
换句话说,插入迭代器的实现保证迭代器将自动“自愈”,即使插入导致容器中潜在的迭代器无效事件。
您的代码存在的问题是,begin
和end
迭代器可能会因插入某些容器类型而失效。您需要在代码中担心begin
和end
,而不是插入迭代器。
与此同时,出于某种原因,你完全倒退了。您似乎关心刷新插入迭代器(这是完全没必要的),同时完全忽略begin
和end
。