std::
中是否有插入迭代器?对于无序集合?据我所知,std::inserter
需要一个迭代器参数。这对于无序容器(至少对于 boost::unordered_set
)是不安全的,因为它们可能会在 insert
期间重新分配操作并渲染通过的 .begin()
迭代器无效。
所以目前我必须传递我自己的迭代器,它本质上是一个 boost::function_output_iterator
使用一个简单地调用 unorderedSet.insert(param1)
的仿函数.
为什么会这样std::inserter
甚至需要 hint
迭代器参数呢?
最佳答案
没有。 hint
的原因参数是std::inserter
用于在插入上下文中需要位置的容器。如您所知,无序容器不是这种情况。vector
在一个容器的例子中,知道 position
是插入的要求。来自 cppreference :
(1) iterator insert( iterator pos, const T& value ); // (until C++11) iterator insert( const_iterator pos, const T& value ); // (since C++11)
(2) iterator insert( const_iterator pos, T&& value ); // (since C++11)
(3) void insert( iterator pos, size_type count, const T& value ); // (until C++11) iterator insert( const_iterator pos, size_type count, const T& value ); // (since C++11)
(4) template< class InputIt > void insert( iterator pos, InputIt first, InputIt last); // (until C++11) template< class InputIt > iterator insert( const_iterator pos, InputIt first, InputIt last ); // (since C++11)
(5) iterator insert( const_iterator pos, std::initializer_list<T> ilist ); // (since C++11)
Inserts elements at the specified location in the container.
1-2) inserts value before pos
3) inserts count copies of the value before pos
4) inserts elements from range [first, last) before pos.
This overload has the same effect as overload (3) if InputIt is an integral type. (until C++11)
This overload only participates in overload resolution if InputIt qualifies as LegacyInputIterator, to avoid ambiguity with the overload (3). (since C++11) The behavior is undefined if first and last are iterators into *this.
5) inserts elements from initializer list ilist before pos.
我知道这不是您要寻找的答案,但是推出自己的答案很容易,即使不是有点冗长:
template<typename Container>
class unordered_inserter {
public:
using iterator_category = std::output_iterator_tag;
using value_type = void;
using reference_type = void;
using difference_type = void;
using pointer = void;
using reference = void;
using container_type = Container;
unordered_inserter& operator++() {return *this;} //no-op
unordered_inserter& operator++(int) {return *this;} //no-op
unordered_inserter& operator*() {return *this;} //no-op
constexpr unordered_inserter& operator=(const typename Container::value_type& value) {
container->insert(value);
return *this;
}
constexpr unordered_inserter& operator=(typename Container::value_type&& value) {
container->insert(std::move(value));
return *this;
}
unordered_inserter(Container* container)
: container(container)
{}
protected:
Container* container;
};
这可能可以重构以支持其他类型的插入,但我认为现在就足够了。
这是我玩的一点:
int main() {
std::unordered_map<int, int> m;
std::istringstream iss("1 2 3 4 5 6");
std::transform(std::istream_iterator<int>(iss), std::istream_iterator<int>(), unordered_inserter(&m), [](int v) {
return decltype(m)::value_type{v, v*v};
});
std::transform(m.begin(), m.end(), std::ostream_iterator<std::string>(std::cout, "\n"), [](auto pair) {
return std::to_string(pair.first) + "," + std::to_string(pair.second);
});
}
Live on Godbolt
这里要注意的一点是,你的断言通过了这个
hint
无序容器不安全的论点是错误的。当operator=
被调用,一个新元素被插入到容器中,iter
成员更新为任何 insert
返回。由于此值必须有效,因此 iter
不可能可能永远无效。
关于c++ - std::为无序集(或映射)插入迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27429705/