Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emplace directly in std::map of pair

Why this code won't compile?

std::map<int,std::pair<int,int>> m;
m.emplace(1,1,1);

Assuming that we can edit the code of std::map::emplace, is it possible to alter it in order to make previous code valid?

like image 711
Humam Helfawi Avatar asked Apr 28 '16 06:04

Humam Helfawi


People also ask

How to use map of pairs in STL?

Map of pairs in STL. Map in STL is used to hash key and value. We generally see map being used for standard data types. We can also use map for pairs. For example consider a simple problem, given a matrix and positions visited, print which positions are not visited. using namespace std; map<pair<int, int>, int> vis;

What is the difference between insert () and emplace () in MAP2?

2. Using emplace: emplace is also used to insert the pairs into the map. This function is similar to “insert ()” discussed above, the only difference being that “in-place” construction of pair takes place at the position of element insertion contrary to insert () which copies or movies existing object.

Can we use map for pairs?

We generally see map being used for standard data types. We can also use map for pairs. For example consider a simple problem, given a matrix and positions visited, print which positions are not visited. This article is contributed by Abhishek Rajput.

How to insert repeated pairs in a map?

The repeated pairs are not inserted if they are present in the destination container. Time complexity: k*log (n) where n is size of map, k is no. of elements inserted. 2. Using emplace: emplace is also used to insert the pairs into the map.


1 Answers

It is invalid for exactly the same reason this is invalid:

std::pair<const int, std::pair<int, int>> p{1, 1, 1};

Because the above is, in essence, what the map's emplace boils down to.

To make it work, you can use the piecewise_construct constructor of std::pair, which was introduced for precisely this purpose:

m.emplace(
  std::piecewise_construct,
  std::forward_as_tuple(1),
  std::forward_as_tuple(1, 1)
);

This will have the desired effect of not calling any unnecessary constructors (even if they would likely be elided).


To answer your hypothetical question about making the "direct" syntax work: in the general case for an arbitrary map<K, V>, no. Imagine this:

struct Proof {
  Proof(int);
  Proof(int, int);
};

std::map<Proof, Proof> m;
m.emplace(1, 1, 1);  // Now what?

You could certainly make it work for the limited case of map<T, std::pair<T, T>>. It would probably be doable for something a bit more general too, with the help of massive amounts of advanced template tricks (think SFINAE left, right, and centre, and then some). Whether that is worth it depends on the details of your situation.

like image 76
Angew is no longer proud of SO Avatar answered Oct 20 '22 17:10

Angew is no longer proud of SO