Joe
Joe

Reputation: 23

How to make an unordered_map only work with predefined keys?

How can I create an unordered_map, which will work only with the keys I want and throw an error otherwise.

For example, like in python:

my_dict = {
    'a': 0,
    'b': 0
}
my_dict['c']  # Will raise an error

But in C++, the equivalent code will initialize a 'c': 0 pair.

What to do? The most obvious solution is to check the key before passing it to the map, but for a huge amount of keys it could get bulky with a lot of ifs.

Upvotes: 1

Views: 165

Answers (3)

lopho
lopho

Reputation: 177

Use the type system. Define an enum with the keys you want, and then only use enum values instead of literals.

enum MyKeys { A, B };
std::unordered_map<MyKeys, int> my_map;
my_map.insert({A,0});
my_map.insert({B,1});
my_map.insert({C,0}); // compile time error
my_map.insert({'C',23}); // compile time error
my_map[A]; // works
my_map[C]; // compile time error
my_map[2]; // compile time error

Upvotes: 0

eerorika
eerorika

Reputation: 238311

but in c equivalent code will initialize 'c': 0 pair. What to do?

Simply don't use operator[].

You can use the at member function instead. It behaves similar to pythons dict:

Returns: A reference to the mapped_­type corresponding to x in *this

Throws: An exception object of type out_­of_­range if no such element is present.

Alternatively, you can use find, which returns an iterator to the element or iterator to end if element doesn't exist instead of throwing an exception.


If you don't want to modify the values, then you can make the map const which will prevent using operator[].


If you want to to keep the map modifiable, but not allow adding elements, then you need to define a wrapper class that contains the map in a private member, and delegates the allowed operations.

Upvotes: 4

doron
doron

Reputation: 28872

Use the find method and not the deference operator to access the unordered map. If an item is not found an end iterator is returned.

Upvotes: 3

Related Questions