std::
中是否有针对无序集的插入迭代器?据我所知,std::inserter
需要一个迭代器参数。这对于无序容器(至少对于boost::unordered_set
)是不安全的,因为它们可能在insert
操作期间重新分配并且使传递的.begin()
迭代器无效。
所以目前我必须传递我自己的迭代器,它基本上是一个boost::function_output_iterator
,带有一个只调用unorderedSet.insert(param1)
的仿函数。
为什么std::inserter
甚至需要 hint
迭代器参数呢?
答案 0 :(得分:2)
没有。之所以需要hint
参数,是因为std::inserter
用于在插入上下文中需要 position 的容器。如您所知,无序容器不是这种情况。
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)
将元素插入容器中的指定位置。
1-2)在pos之前插入值
3)在值之前插入计数副本
4)插入范围[first,last) pos之前的元素。
如果InputIt是整数类型,则此过载与过载(3)具有相同的效果。 (直到C ++ 11)
仅在InputIt符合LegacyInputIterator的情况下,此重载才参与重载解析,以避免与重载(3)产生歧义。 (自C ++ 11起) 如果first和last是* this的迭代器,则该行为是不确定的。
5)在pos之前在初始化列表ilist中插入元素。
我知道这不是您要寻找的答案,但是推出您自己的答案就足够容易了,即使有点冗长:
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);
});
}
这里要注意的一点是,您断言将此hint
参数传递给无序容器是不安全的,这是错误的。调用operator=
并将新元素插入容器后,iter
成员将更新为insert
返回的值。由于此值必须有效,因此无法使iter
无效。