4

So most likely this question had been asked already. Couldn't find it.

Every time I define a std::map and want to insert some value to it, I use this piece of code:

using IntVector = vector < int > ;
map<int, IntVector> mapTmp;

int iKey = 7;
int iVal = 9;
if (mapTmp.find(iKey) == mapTmp.end())
    mapTmp.insert(pair<int, IntVector>(iKey, IntVector()));
mapTmp[iKey].push_back(iKey);

What annoys me is the 3 lines:

if (mapTmp.find(iKey) == mapTmp.end())
    mapTmp.insert(pair<int, IntVector>(iKey, IntVector()));
mapTmp[iKey].push_back(iVal);

Python offer a very useful dict function called: setdefault, that essentially combine those 3 lines into one beautiful line. Say I want to write it in C++, it would be:

mapTmp.setdefault(iKey, IntVector()).push_back(iVal);

Questions

  1. Does C++ offer such functionality?
  2. If not, does everyone write those 3 lines all the time?
idanshmu
  • 5,061
  • 6
  • 46
  • 92
  • 1
    As for the first two lines, `!mapTmp.count(iKey)` is a suitable replacement for `mapTmp.find(iKey) == mapTmp.end()` and `{iKey, {}}` is a suitable replacement for `pair(iKey, IntVector())` in that context. – chris Jul 16 '15 at 06:26
  • There's also `make_pair(iKey, IntVector())` if you want it to be absolutely clear that it's a pair and not some other two-member aggregate. – celticminstrel Jul 16 '15 at 06:37

1 Answers1

6

The map defined by the C++ standard library has the somewhat counter-intuitive behaviour that merely calling operator[] can mutate the array. In other words, your "if not in map then insert a default" logic is entirely superfluous - the following two segments are equivalent:

if (mapTmp.find(iKey) == mapTmp.end())
    mapTmp.insert(pair<int, IntVector>(iKey, IntVector()));
mapTmp[iKey].push_back(iVal);

and:

mapTmp[iKey].push_back(iVal);

In the second case, if iKey does not exist in the map, it is first default-initialized. For a vector, that's the same as inserting an empty vector.

For the general case that Python's setdefault covers, I don't know of anything. You might be able to get the effect by providing a custom allocator for the map, but I don't think I'd recommend it.

celticminstrel
  • 1,637
  • 13
  • 21