0
int c = counts.at(v).at(id);
std::cout << c;
counts.at(v).emplace(id,c+1);
std::cout << counts.at(v).at(id);

counts is an unordered_map of unordered_map. The first cout prints 1, the second prints 1, why it is not incremented ?

François
  • 401
  • 3
  • 9

2 Answers2

3

emplace does not insert anything if that key already exists, so instead you could use the following

counts.at(v)[id] += 1;

The operator[] will either default construct a value if that key does not exist, or will return a modify-able reference if it does exist

Cory Kramer
  • 98,167
  • 13
  • 130
  • 181
  • 1
    It will [value initialize](http://en.cppreference.com/w/cpp/language/value_initialization) the object, which in the case of `int`, is different from default construction. (initializing it to zero vs leaving it uninitialized) – Benjamin Lindley Feb 17 '18 at 18:36
  • @LightnessRacesinOrbit: Perhaps my sentence construction was confusing, but that is precisely what I meant, that the int will be initialized to zero. The first sentence mentioned value initialization first, and default construction second. The clarification analogously mentioned initialization to zero first, followed by non-initialization. – Benjamin Lindley Feb 17 '18 at 20:11
  • @BenjaminLindley: Yep okay I'm with you now. – Lightness Races in Orbit Feb 17 '18 at 20:16
1

You've already found how to get to the element in question:

counts.at(v).at(id);

Per documentation, this is a reference (until you copy it into a new object, like c), so you can simply increment it:

counts.at(v).at(id)++;

Or, if we're assuming both keys already exist (or you don't mind them being created if they don't), as they do in your code:

counts[v][id]++;

… which, in my opinion, is much easier to read.

The emplace function is for creating a new element where none previously existed.


In totality, then:

std::cout << counts[v][id] << ' ';
counts[v][id]++;
std::cout << counts[v][id];

Or, if you don't want the repeated lookups:

auto& elm = counts[v][id];
std::cout << elm << ' ';
elm++;
std::cout << elm;

You could even shorten it further (though this is less clear):

auto& elm = counts[v][id];
std::cout << elm++ << ' ';
std::cout << elm;

Or, since C++17:

auto& elm = counts[v][id];
std::cout << elm++ << ' ' << elm;
Lightness Races in Orbit
  • 358,771
  • 68
  • 593
  • 989