std::map: Creating/replacing 不可默认构造的元素
std::map: Creating/replacing an element when it is not default-constructible
假设您有一个 class 不是默认构造的。
class A {
private:
int a;
public:
A() = delete;
A(int a0) : a(a0) {}
};
现在,我们有一些映射 Int --> A,std::map<int, A> mapping
。假设我们要为某个键 0 创建一个新映射,如果该键存在,我们要替换旧值。默认构造的 classes 的方法是这样的:
mapping[0] = A(4);
然而,这对于 class A 将失败,因为 operator[] 首先构造 A 的默认实例,然后才会分配 A(4)
的值。一般来说(即非默认构造的 classes)这样做的一种方法是:
auto it = mapping.find(0);
if (it == mapping.end()) {
mapping.insert(0, A(4));
}
else {
it->second = A(4);
}
我的问题是:这真的是 (C++) 预期的方式吗?我觉得这不对;作为一名程序员,我不想为这么少的东西写这么多代码。但似乎没有简单的出路:我查找了常见的映射方法(插入、放置、emplace_hint),如果密钥已经存在,它们都什么都不做。
I have looked up common map methods (insert, emplace, emplace_hint) and all of them do nothing if the key is already present.
C++17 已通过 std::map::insert_or_assign
:
解决了这一点
template <class M>
pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
If a key equivalent to k
already exists in the container, assigns std::forward<M>(obj)
to the mapped_type
corresponding to the key k
. If the key does not exist, inserts the new value as if by insert, constructing it from value_type(k, std::forward<M>(obj)
).
这使得
auto it = mapping.find(0);
if (it == mapping.end()) {
mapping.insert(0, A(4));
}
else {
it->second = A(4);
}
看起来像
mapping.insert_or_assign(0, A(4));
假设您有一个 class 不是默认构造的。
class A {
private:
int a;
public:
A() = delete;
A(int a0) : a(a0) {}
};
现在,我们有一些映射 Int --> A,std::map<int, A> mapping
。假设我们要为某个键 0 创建一个新映射,如果该键存在,我们要替换旧值。默认构造的 classes 的方法是这样的:
mapping[0] = A(4);
然而,这对于 class A 将失败,因为 operator[] 首先构造 A 的默认实例,然后才会分配 A(4)
的值。一般来说(即非默认构造的 classes)这样做的一种方法是:
auto it = mapping.find(0);
if (it == mapping.end()) {
mapping.insert(0, A(4));
}
else {
it->second = A(4);
}
我的问题是:这真的是 (C++) 预期的方式吗?我觉得这不对;作为一名程序员,我不想为这么少的东西写这么多代码。但似乎没有简单的出路:我查找了常见的映射方法(插入、放置、emplace_hint),如果密钥已经存在,它们都什么都不做。
I have looked up common map methods (insert, emplace, emplace_hint) and all of them do nothing if the key is already present.
C++17 已通过 std::map::insert_or_assign
:
template <class M> pair<iterator, bool> insert_or_assign(const key_type& k, M&& obj);
If a key equivalent to
k
already exists in the container, assignsstd::forward<M>(obj)
to themapped_type
corresponding to the keyk
. If the key does not exist, inserts the new value as if by insert, constructing it fromvalue_type(k, std::forward<M>(obj)
).
这使得
auto it = mapping.find(0);
if (it == mapping.end()) {
mapping.insert(0, A(4));
}
else {
it->second = A(4);
}
看起来像
mapping.insert_or_assign(0, A(4));