简体   繁体   English

如何从STL容器中获取仅移动类型?

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

Let's consider an std::unordered_set of std::unique_ptr<T> as an example. 我们以std::unique_ptr<T>std::unordered_set为例。 Can I move an element of the set elsewhere ? 我可以在其他位置移动该组的元素吗?

#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
    }
}

I have a very practical example of code where I would like to do this but am reduced to use a std::shared_ptr . 我有一个非常实用的代码示例,我想这样做,但我减少使用std::shared_ptr Do you know of another (better ?) alternative ? 你知道另一个(更好吗?)的选择吗?

In C++03, C++11, and C++14, not directly. 在C ++ 03,C ++ 11和C ++ 14中,不是直接的。 You'd have to change the type to be something like: 您必须将类型更改为:

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

With this, you can write: 有了这个,你可以写:

std::unordered_set<handle<int>> mySet;
// initialize as appropriate

for (auto& elem : mySet) {
    myVector.push_back(std::move(elem.owning_ptr));        
}
mySet.clear();

This will still be well-defined behavior because we're not messing with any of the container internals - the observing pointer will still be valid through the end of the clear() , just now myVector owns it instead. 这仍然是明确定义的行为,因为我们没有搞乱任何容器内部 - 观察指针在clear()结束时仍然有效,只是现在myVector拥有它。


In C++17, we can do this directly and more simply with the help of extract() : 在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()));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 boost multi_index-如果元素的类型为仅移动,如何将元素从一个容器添加到另一个容器? - boost multi_index - how to add an element from one container to another if its type is move-only? 仅移动类型的back_inserter - back_inserter for move-only type 插入只移动类型的向量 - Inserting into a vector of move-only type 仅移动类型返回到转换构造函数 - Move-only type returned into converting constructor 在仅移动类型上强制复制(然后销毁) - Force copy (then destroy) on move-only type C ++ 11 STL容器支持仅移动类型,并且对开始和结束具有O(1)写入权限 - C++11 STL container that supports move-only types and has O(1) write-access to beginning and end 包含仅移动类型的类的构造函数是应该通过引用还是通过右值引用来接收仅移动类型? - Should a constructor for a class that contains a move-only type receive the move-only type by reference or by rvalue reference? 一个类型是否只能移动,只是因为复制可能很昂贵? - Should a type be move-only, just because copying may be expensive? 我可以列表初始化一个只移动类型的向量吗? - Can I list-initialize a vector of move-only type? 向量<map<move-only type> &gt; 不能用 MSVC 编译</map<move-only> - vector<map<move-only type>> does not compile with MSVC
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM