[英]add to std::map with a non-default-constructible mapped value
I have a std::map<Key, T>
with a non-default-constructible T
.我有一个带有非默认构造
T
的std::map<Key, T>
。 T
operloads operator +
so that I know how to add objects of T
. T
operloads operator +
以便我知道如何添加T
的对象。 I am frequently in the situation that I need to add a particular value at at a given Key k
.我经常遇到需要在给定
Key k
处添加特定值的情况。 If T
were default constructible I would do something like如果
T
是默认可构造的,我会做类似的事情
std::map<Key, T> map;
Key k;
T t;
map[k] += t;
However I am forced to use expressions like但是我被迫使用像
if (map.contains(k)) map.at(k) += t;
else map.emplace(k, t);
Is there a way of avoiding the lookup and behave like []
would do with a default value?有没有一种方法可以避免查找并表现得像
[]
会使用默认值? Do I need to change the allocator of map
so that by default inserts t
?我是否需要更改
map
的分配器以便默认插入t
?
To look-up only once, you might do something like:要仅查找一次,您可以执行以下操作:
if (auto [it, inserted] = map.insert(k, t); !inserted) {
*it += t;
}
What you want, in general, is try_emplace
.通常,您想要的是
try_emplace
。 This is in C++17.这是在 C++17。
This function will emplace if and only if the key is missing, otherwise it is guaranteed to do nothing to the value.当且仅当密钥丢失时,这个 function 才会被放置,否则它保证不会对值做任何事情。 This is unlike
insert
or emplace
, which may freely copy or move your value even if the key exists.这与
insert
或emplace
不同,即使键存在,它们也可以自由复制或移动您的值。 This is important if your type is like unique_ptr
, or to avoid unnecessary copies.如果您的类型类似于
unique_ptr
,或者为了避免不必要的复制,这一点很重要。
#include <iostream>
#include <map>
#include <string>
struct Foo {
explicit Foo(int i) : i(i) {}
Foo(const Foo&) = delete;
Foo(Foo&&) = default;
Foo& operator+=(const Foo& other) {
i += other.i;
return *this;
}
int i;
};
template <typename K, typename V>
V& emplace_or_add(std::map<K, V> & map, const K& key, V&& value) {
auto [iter, was_emplaced] = map.try_emplace(key, std::forward<V>(value));
if (!was_emplaced) {
iter->second += value;
}
return iter->second;
}
int main() {
std::map<char, Foo> map;
map.emplace('a', 5);
emplace_or_add(map, 'a', Foo(3));
emplace_or_add(map, 'b', Foo(2));
std::cout << "a: " << map.at('a').i << std::endl;
std::cout << "b: " << map.at('b').i << std::endl;
}
http://coliru.stacked-crooked.com/a/2b739a55ad791507 http://coliru.stacked-crooked.com/a/2b739a55ad791507
a: 8
b: 2
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.