5

I would like to create an unordered_map of <string, atomic<int>>. I would use this to increment (fetch_add), store or load the values of the atomic based on a string (the key). For example, say I have 10 atomic integer counters, but I want to only get the values of 4 or them. I would like a unordered_map that looked like this:

unordered_map<string, atomic<int>> myValues = {
    {"first", atomic<int>(0)},
    {"second", atomic<int>(0)}, ... the last key being "tenth"}
};

Then say I had a vector of strings like

vector<string> wanted = {"first", "third", "tenth"};

The I would like to do the following:

for (auto want: wanted) {
    cout <<  myValues[want].load() << endl;

This should print out the values for the keys in wanted.

Can I do this? If I try to create a map as above, I get the error message that the assignment operator for atomic is deleted? Is there a way to do this?

Praetorian
  • 106,671
  • 19
  • 240
  • 328
Mark
  • 2,058
  • 2
  • 35
  • 64

1 Answers1

8

Sure, creating an unordered_map<string, atomic<int>> is possible, but you cannot initialize it using the initializer_list constructor because atomic<T> objects are neither moveable nor copyable.

Since the values in your map can be constructed using a single argument, you can use the emplace member function.

std::unordered_map<std::string, std::atomic<int>> m;

for(auto const& key : {"first", "second", "third", "fourth"})
    m.emplace(key, 0);

If your key/value type constructor takes more than one argument, to avoid copies and moves, you must use std::pair's piecewise construction constructor and the emplace member function.

for(auto const& key : {"first", "second", "third", "fourth"})
    m.emplace(std::piecewise_construct,
              std::forward_as_tuple(key),
              std::forward_as_tuple(0));

If your compiler has C++17 support, and the key type can be constructed using a single argument, then you can also use the less verbose try_emplace member function

for(auto const& key : {"fifth", "sixth", "seventh", "eight"})
    m.try_emplace(key, 0);
Praetorian
  • 106,671
  • 19
  • 240
  • 328