繁体   English   中英

使用不可默认构造的映射值添加到 std::map

[英]add to std::map with a non-default-constructible mapped value

我有一个带有非默认构造Tstd::map<Key, T> T operloads operator +以便我知道如何添加T的对象。 我经常遇到需要在给定Key k处添加特定值的情况。 如果T是默认可构造的,我会做类似的事情

std::map<Key, T> map;
Key k;
T t;

map[k] += t;

但是我被迫使用像

if (map.contains(k)) map.at(k) += t;
else map.emplace(k, t);

有没有一种方法可以避免查找并表现得像[]会使用默认值? 我是否需要更改map的分配器以便默认插入t

要仅查找一次,您可以执行以下操作:

if (auto [it, inserted] = map.insert(k, t); !inserted) {
    *it += t;
}

通常,您想要的是try_emplace 这是在 C++17。

当且仅当密钥丢失时,这个 function 才会被放置,否则它保证不会对值做任何事情。 这与insertemplace不同,即使键存在,它们也可以自由复制或移动您的值。 如果您的类型类似于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

a: 8
b: 2

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM