如何从STL容器中获得仅限移动类型

How to get a move-only type out of a STL container?

本文关键字:移动 类型 STL      更新时间:2023-10-16

std::unique_ptr<T>std::unordered_set为例。我可以把集合中的元素移到别处吗?

#include <unordered_set>
#include <iostream>
#include <memory>
#include <vector>
int main()
{
    std::unordered_set<std::unique_ptr<int>> mySet;
    mySet.insert(std::make_unique<int>(1));
    mySet.insert(std::make_unique<int>(2));
    mySet.insert(std::make_unique<int>(3));
    std::vector<std::unique_ptr<int>> myVector;
    for (auto&& element : mySet)
    {
        std::cout << *element << std::endl;
        //myVector.push_back(element); won't compile as you can only get a const ref to the key
    }
}

我有一个非常实用的代码示例,我想这样做,但我减少了使用std::shared_ptr。你知道另一种(更好的)选择吗?

在c++ 03、c++ 11和c++ 14中,不直接。您必须将类型更改为:

template <class T>
struct handle {
    mutable std::unique_ptr<T> owning_ptr;
    T* observing_ptr; // enforce that observing_ptr == owning_ptr.get() on construction
    // define operator<, hash, etc. in terms of the observing ptr
};

你可以这样写:

std::unordered_set<handle<int>> mySet;
// initialize as appropriate
for (auto& elem : mySet) {
    myVector.push_back(std::move(elem.owning_ptr));        
}
mySet.clear();

这仍然是定义良好的行为,因为我们没有弄乱任何容器内部-观察指针在clear()结束时仍然有效,只是现在myVector拥有它。


在c++ 17中,我们可以通过extract():

直接且更简单地完成此操作:
for (auto it = mySet.begin(); it != mySet.end();  
{
    std::cout << **it << std::endl;
    myVector.push_back(std::move(
        mySet.extract(it++).value()));
}