Inserting value into the map with multiple keys

Lately, I’ve been working on a GNSS-related project and taking my PhD exams and haven’t had any time to write any articles. I tried to make this project useful for my self-education as possible without compromising the quality of the software in general. There are several little tricks I’ve learned which I’ll wrap in articles for future use. Let me share one of those just to start writing again.

As you all may know, code repetition is the root of evil. Every time you can refactor some repeating code into a function, you improve the codebase. As a part of the project, I needed to have the same value at multiple keys in the map (std::unordered_map actually). The most straightforward solution is just to copy the code:

map[key1] = value;
map[key2] = value;
map[key3] = value;
map[key4] = value;


There is a way to refactor this kind of code into the function and it’s called the parameter packs. However, parameter pack is a template, that just expands to whatever types you pass to it. In our case, we need to make pass all the keys of the same type. Don’t forget to check this article by Jonathan as a way to provide such a guarantee, but it’s a bit excessive in our case.

Any parameter pack, if the values are of the same type, may be converted to the std::initializer_list<T>. Therefore, such a task may be rewritten in the following snippet:

template <typename ...Args>
bool RegisterMessage(const std::function<bool(int)>& predicate, Args... message_types) {
auto& map = GetMap();
for (auto& key : {message_types...})
map[key] = predicate;
return true;
}


And the usage:

auto a = RegisterMessage([](int val){return val == 12345;},   1, 2, 3, 4, 5);
auto b = RegisterMessage([](int val){return val == 123;},     6, 7, 8);