简体   繁体   English

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

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

I have a std::map<Key, T> with a non-default-constructible T .我有一个带有非默认构造Tstd::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.这与insertemplace不同,即使键存在,它们也可以自由复制或移动您的值。 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.

相关问题 std::map emplace 不可移动不可复制非默认可构造类型 - std::map emplace non-movable non-copyable non-default-constructible type 使用非默认可构造类型填充std :: array(无可变参数模板) - Populate std::array with non-default-constructible type (no variadic templates) 初始化非默认可构造元素的 std::array? - Initializing an std::array of non-default-constructible elements? 如何初始化std :: array <T, 2> 其中T是不可复制的,非默认可构造的? - How to initialize an std::array<T, 2> where T is non-copyable and non-default-constructible? 如何正确初始化非默认可构造的类成员? - How to properly initialize non-default-constructible class member? 如何初始化不可默认构造的不可复制对象的元组? - How to initialize a tuple of non-default-constructible not-copyable objects? 移动具有非默认构造 class 保护的构造函数 - Move constructor with protection for non-default-constructible class 创建非默认可构造类的虚拟对象 - Create dummy object of non-default-constructible class 如何创建C ++ 11不可默认构造的分配器? - How to create a C++ 11 non-default-constructible allocator? 使用 Boost.Python 导出非默认可构造类 - Exporting non-default-constructible classes with Boost.Python
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM