5

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?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Humam Helfawi
  • 19,566
  • 15
  • 85
  • 160

1 Answers1

11

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.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455