Search code examples
c++global-variablesc++20unordered-map

How to define an unordered_map at global level?


I am trying to define two unordered maps at global level, I define them with loops and I don't want to put the loops to main().

More specifically I am trying to define a base-36 alphabet, I use Arabic digits for digits 0-9, then Basic Latin alphabet for digits 10-35, one map is for converting string to integer, and it should support UPPERCASE and lowercase, the other for converting integer to its string representation in given base, and it should be lowercase only.

Here is my code, obviously it doesn't work:

#include <unordered_map>

using namespace std;
const unordered_map<string, int> digits;
const unordered_map<int, string> alphabet;

for (int i = 0; i < 10; i++) {
    string d = char(i + 48);
    digits[d] = i;
    alphabet[i] = d;
}

for (int i = 10; i < 36; i++) {
    string upper = char(i + 55);
    string lower = char(i + 87);
    digits[upper] = i;
    digits[lower] = i;
    alphabet[i] = lower;
}

I am aware that if I put the loops inside the main() function, it should work. But I don't want to do that.

Is there a way to initialize them directly, and use assignment operator to define them, possibly with comprehension?

Something like the following Python code:

DIGITS = {
    **{chr(i + 48): i for i in range(10)},
    **{chr(i + j): i for i in range(10, 36) for j in (55, 87)},
}

ALPHABET = {
    **{i: chr(i + 48) for i in range(10)},
    **{i: chr(i + 87) for i in range(10, 36)},
}

Somewhat irrelevant, but here is my current working program that converts strings to numbers and vice-versa, I am trying to get rid of the if statements inside the conversion functions.

And I want to use unordered_map here to familiarize myself with it, and compare and contrast it with Python's dict.


Solution

  • Use a directly invoked lambda expression to initialize your variable.


    #include <unordered_map>
    #include <string>
    #include <iostream>
    
    // using namespace std; <== do not do this
    const auto digits = [] 
    {
        std::unordered_map<std::string, int> digits;
        for (int i = 0; i < 10; i++)
        {
            digits.insert({ std::to_string(i), i });
        }
        return digits;
    }(); // make a lambda expression and immediately invoke it.
    
    int main()
    {
        // use a range-based for loop + structured binding
        // to show content of the map
        for (const auto& [key, value] : digits)
        {
            std::cout << "[" << key << ", " << value << "]\n";
        }
        return 0;
    }