6

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?

4
  • 1
    atomic types are neither copyable nor movable Commented Sep 4, 2017 at 2:07
  • So that means my approach is DOA? Is there a different way to accomplish the same sort of thing? Commented Sep 4, 2017 at 2:08
  • 1
    Instead of trying to copy atomic values (no no!) you can define the init data separately and just loop through it and emplace it in your map. Commented Sep 4, 2017 at 2:08
  • @Alf, can you give me a simple example? Commented Sep 4, 2017 at 2:12

1 Answer 1

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); 
Sign up to request clarification or add additional context in comments.

2 Comments

Why try_emplace ? m.emplace(key, 0); is just fine (without C++17 support)
@LWimsey Well, wasn't that silly? Clearly a case of overthinking it. Fixed now.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.