如何使用提取将不可复制的元素从std :: set移动到std :: map?

问题描述

请考虑以下内容:

const getAll = async () => {
  try {
    const result: any = {};
    const keys = await AsyncStorage.getAllKeys();
    for (const key of keys) {
      const val = await AsyncStorage.getItem(key);
      result[key] = val;
    }
    return result;
  } catch (error) {
    alert(error);
  }
};

我使用#include <set> #include <map> struct MyClass { MyClass(int i); MyClass(MyClass const&) = delete; ~MyClass(); bool operator<(const MyClass& r) const { return v < r.v; } int v; }; void map_set_move_test() { std::set<MyClass> s1,s2; std::map<int,MyClass> m1; s1.emplace(123); s2.insert(std::move(s1.extract(s1.begin()))); // This fails m1.insert(std::move(std::make_pair(1,std::move(s2.extract(s2.begin()).value())))); } 成功将元素从std::set::extract移动到另一个std::set,如下所示:

std::set

但是编译器不允许通过以下方式将元素移动到s2.insert(std::move(s1.extract(s1.begin())));

std::map

任何帮助将不胜感激。 Link to compiler explorer

解决方法

这是一个有问题的示例,因为MyClass不仅是不可复制的,而且还隐含地不可移动-这可能不是您的意思。 (我认为MyClass由于您明确删除了复制构造函数而变得不动;请参阅this answer。)

如果您确实将MyClass设为可移动,则如下所示:

class MyClass : NonCopyable
{
public:
    MyClass(int i) : v(i) {
        std::cout << "constructor" << std::endl;
    }
    MyClass(MyClass&& other) : v(other.v) {
        std::cout << "move constructor" << std::endl;
    }
    ~MyClass() {
        std::cout << "destructor" << std::endl;
    }
    bool operator<(const MyClass& r) const {
        return v < r.v;
    }

    int v;
};

说的话,一切似乎都进展顺利。

m1.emplace(
    1,std::move( 
        s2.extract(s2.begin()).value() 
    )
);

您可以在GodBolt上看到它。


PS-正如@DavisHerring所建议的那样,如果您不想覆盖现有值,则可能要使用try_emplace()方法。

,

extract的点和insert的相应重载是在没有内存分配的情况下操纵基于节点的容器。 (一种有趣的操作是更改std::map键。)由于节点是不同类型( viz。,一个有键而另一个没有键),因此在这里不起作用。您只需将其与常规 insert(或更符合人体工程学的try_emplace)一起使用。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...