Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is try_emplace not implemented for std::multimap?

Tags:

c++

c++17

C++17 introduces the try_emplace method for std::map, so now I can write code like below:

struct Test
{
    Test(int i, int j){}
};
std::map<int, Test> tmap;
tmap.try_emplace(10, 10, 10);

But there is no try_emplace for std::multimap<int, Test>, so piecewise_construct is still needed.

Is there a technical reason for this?

like image 345
Lei Yu Avatar asked Dec 14 '18 01:12

Lei Yu


People also ask

What is multimap size in C++ STL?

multimap size () function in C++ STL – Returns the number of elements in the multimap container. multimap::emplace () in C++ STL – Inserts the key and its element in the multimap container. multimap::begin () and multimap::end () in C++ STL – begin () returns an iterator referring to the first element in the multimap container.

What is the use of emplace in Python?

Inserts a new element into the container constructed in-place with the given args . Careful use of emplace allows the new element to be constructed while avoiding unnecessary copy or move operations.

What is multimap in C++?

Multimap in C++ Standard Template Library (STL) Multimap is similar to map with an addition that multiple elements can have same keys. Rather than each element being unique, the key value and mapped value pair has to be unique in this case.

What is try_emplace method in maps and unordered maps?

In this article, we are going to learn try_emplace method in Maps and Unordered Maps. This method was added in C++17 (i.e gcc 9.1) version. This new function proposed behaves similarly to emplace (), but has an advantage that is, it will not construct the object associated with the key, if the key already exists.


2 Answers

is there a technical reason for this?

Yes. The purpose of try_emplace() is to not do anything if the key already exists in the map. But for std::{unordered_,}multi{map,set}, you can have multiple values for each key. That is, indeed, the point of these containers: to have multiple values for a given key.

As a result, try_emplace() cannot fail for these containers - so it would be confusing and pointless to provide such a function.


Based on the comments, it seems that the motivation is just the part of try_emplace() that makes it easier to emplace a value. You can write a helper function for that:

template <typename Map, typename Key, typename... Args>
auto emplace_value(Map& map, Key&& key, Args&&... args) {
    return map.emplace(std::piecewise_construct,
                       std::forward_as_tuple(std::forward<Key>(key)),
                       std::forward_as_tuple(std::forward<Args>(args)...));
}

Which would let you write emplace_value(tmap, 10, 10, 10), even for {unordered_,}multimap.

like image 119
Barry Avatar answered Oct 17 '22 18:10

Barry


It is not necessary since for multimap case since there is no unique key, try_emplace would never fail. The rational for adding try_emplace to map was all the error prone code needed to deal with the case that key already exists, see the proposal n4279 (emphasis mine):

The existing interface of unique-keyed map containers (std::map, std::unordered_map) is slightly underspecified, which makes certain container mutations more complicated to write and error-prone than necessary. This paper describes new member function templates to fill this gap.

The justification and rationale for the new interface are given in N3873. The initial reaction to N3873 in Issaquah was that the existing map interfaces should be fixed rather than adding new interfaces. We explored this idea in N4006 in Rapperswil and decided that the original proposal was preferable (with some name changes). This paper only summarises the proposed extension without repeating the original discussion. We only restate the motivating code snippet here for motivation:

std::map<std::string, std::unique_ptr<Foo>> m;
m["foo"] = nullptr;

auto ptr = std::make_unique_ptr<Foo>;
auto res = m.emplace("foo", std::move(ptr));

assert(ptr);    // ??? (may or may not fire)
like image 6
Shafik Yaghmour Avatar answered Oct 17 '22 16:10

Shafik Yaghmour