Due to the dynamic typing nature of Python, Python’s dict serves as a good container for passing a variety of values of different types to functions. The key of dict could be values which are hashable, and the value of dict could be values of any type.
C++, however, is a static typing programming language. Although it also has hash table based data structure, such as unordered_map and map, the conventional usages of the hash table data structure are very limited. The variable type needs to be determined during compile time, and by default, there should be only one type for the key values and the value values respectively, which makes the C++ “dictionary” less flexible to use.
C++ standard 17 introduces a new type std::any serving as a type-safe container for single values of any type, as long as the value is copiable. This std::any would make the usage of C++ dictionary more flexible.
In this blog post, I am going to talk about how to create C++ dictionary with std::any as the type for the stored values.
Examples
Personal Informatoin
We would like to implement a dictionary for Michael’s personal information. In Python, we would use dict and in C++ we would use unordered_map.
name = "Michael" age = 20 credit_history = [10,20,30] id = "US123456" books = BookCollections(books=["Chess", "Go"])
personal_information["name"] = name personal_information["age"] = age personal_information["credit_history"] = credit_history personal_information["id"] = id personal_information["books"] = books
if ((name != retrieved_name) or (age != retrieved_age) or (credit_history != retrieved_credit_history) or (id != retrieved_id) or (books != retrieved_books)): print("Dictionary Failed!") else: print("Dictionary Worked!") if __name__ == "__main__": main()
We ran the Python program and got the following result:
1 2
$ python python_dict.py Dictionary Worked!
C++ Implementation
With a dictionary of type std::unordered_map<std::string, std::any>, the stored value could be any type.
std::string retrievedName; int retrievedAge; std::vector<int> retrievedCreditHistory; char* retrievedId; BookCollections retrievedBooks;
// Retrieving values requires casting the values back to its original type // Otherwise their types are std::any which is rather meaningless retrievedName = std::any_cast<std::string>(personalInformation["name"]); retrievedAge = std::any_cast<int>(personalInformation["age"]); retrievedCreditHistory = std::any_cast<std::vector<int>>(personalInformation["credit_history"]); retrievedId = std::any_cast<char*>(personalInformation["id"]); retrievedBooks = std::any_cast<BookCollections>(personalInformation["books"]);
Even with std::any, the C++ dictionary is not as convenient as the Python dictionary. After all, it is a static typing programming language.
It should be noted that the keys in a Python dictionary could be of any hashable typed values. This means that you can use string and integer interchangeably as the key values for the same dictionary in Python. However, this is not the case in C++ dictionary even with std::any. In C++, we could not do std::unordered_map<std::any, std::any> because the key value of type std::any is not hashable.