C++ std::为无序集(或映射)插入迭代器?

C++ std::为无序集(或映射)插入迭代器?,c++,unordered-set,invalidation,insert-iterator,C++,Unordered Set,Invalidation,Insert Iterator,对于无序集,std::中是否有插入迭代器?就我所见,std::inserter需要一个迭代器参数。这对于无序容器是不安全的(至少对于boost::unordered_set),因为它们可能在insert操作期间重新分配,并使传递的.begin()迭代器无效 因此,目前我必须传递自己的迭代器,它本质上是一个boost::function\u output\u迭代器,带有一个只调用unorderedSet.insert(param1)的函子 为什么std::inserter甚至需要提示迭代器参数?没

对于无序集,
std::
中是否有插入迭代器?就我所见,
std::inserter
需要一个迭代器参数。这对于无序容器是不安全的(至少对于
boost::unordered_set
),因为它们可能在
insert
操作期间重新分配,并使传递的
.begin()
迭代器无效

因此,目前我必须传递自己的迭代器,它本质上是一个
boost::function\u output\u迭代器
,带有一个只调用
unorderedSet.insert(param1)
的函子


为什么
std::inserter
甚至需要
提示
迭代器参数?

没有。之所以需要
hint
参数,是因为
std::inserter
用于在插入上下文中需要位置的容器。如您所知,无序容器的情况并非如此

vector
在容器示例中,插入时需要知道
位置。发件人:




(4)
模板<类输入>
无效插入(迭代器位置,先输入,后输入);//(直到C++11)
模板<类输入>
迭代器插入(常量迭代器位置,先输入,后输入);//(从C++11开始)

(5)
迭代器插入(const_iterator pos,std::initializer_list ilist);//(从C++11开始)
在容器中的指定位置插入元素

1-2)在pos前插入值 3) 在pos前插入值的计数副本 4) 在pos之前插入范围[first,last)中的元素
如果InputIt是整数类型,则此重载与重载(3)具有相同的效果。(直到C++11)
若InputIt符合LegacyInputIterator的条件,则此重载仅参与重载解析,以避免重载的歧义(3)。(自C++11起) 如果第一个和最后一个是*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;
};
模板
类无序插入器{
公众:
使用迭代器_category=std::output_iterator_标记;
使用值_type=void;
使用引用类型=无效;
使用差异类型=无效;
使用指针=void;
使用引用=无效;
使用容器类型=容器;
无序插入器和运算符++(){return*this;}//无操作
无序插入器和运算符++(int){return*this;}//无操作
无序插入器和运算符*(){return*this;}//无操作
constexpr无序\u插入器和运算符=(constTypeName容器::值\u类型和值){
容器->插入(值);
归还*这个;
}
constexpr无序\u插入器和运算符=(typename容器::值\u类型和值){
容器->插入(标准::移动(值));
归还*这个;
}
无序插入器(容器*容器)
:容器(容器)
{}
受保护的:
集装箱*集装箱;
};
这可能可以被重构以支持其他类型的插入,但我认为这就足够了

这是我在玩的游戏:

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);
    });
}
intmain(){
std::无序映射m;
标准:istringstream iss(“123456”);
std::transform(std::istream_迭代器(iss),std::istream_迭代器(),无序插入器(&m),[](int v){
返回decltype(m):值\类型{v,v*v};
});
std::transform(m.begin(),m.end(),std::ostream_迭代器(std::cout,“\n”),[](自动对){
返回std::to_字符串(pair.first)+“,”+std::to_字符串(pair.second);
});
}

这里需要注意的是,您断言将此
hint
参数传递给无序容器是不安全的,这是错误的。当调用
operator=
并在容器中插入新元素时,
iter
成员将更新为
insert
返回的任何值。因为此值必须有效,所以t在这里,
iter
是不可能失效的

(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)
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);
    });
}