Real-World Examples of Metaprogramming II
Learn how to use the compile-time hash sum calculation in metaprogramming.
Example 2: hash strings at compile time
Let’s say we have a resource system consisting of an unordered map of strings that identifies bitmaps. If a bitmap is already loaded, the system returns the loaded bitmap; otherwise, it loads the bitmap and returns it:
// External function which loads a bitmap from the filesystemauto load_bitmap_from_filesystem(const char * /*path*/) -> Bitmap {// ...return Bitmap{};}// Bitmap cacheauto get_bitmap_resource(const PrehashedString& path) -> const Bitmap& {// Static storage of all loaded bitmapsstatic auto loaded_bitmaps = std::unordered_map<PrehashedString, Bitmap>{};// If the bitmap is already in loaded_bitmaps, return itif (loaded_bitmaps.count(path) > 0) {return loaded_bitmaps.at(path);}// The bitmap isn’t already loaded, load and return itauto bitmap = load_bitmap_from_filesystem(path.c_str());loaded_bitmaps.emplace(path, std::move(bitmap));return loaded_bitmaps.at(path);}
The bitmap cache is then utilized wherever a bitmap resource is needed:
- If it’s not loaded yet, the
get_bitmap_resource()
function will load and return it - If it’s already been loaded somewhere else, the
get_bitmap_resource()
will simply return the loaded function
So, independent of which of these draw functions is executed first, the second one will not have to load the bitmap from disk:
auto draw_something() {const auto& bm = get_bitmap_resource("my_bitmap.png");draw_bitmap(bm);}auto draw_something_again() {const auto& bm = get_bitmap_resource("my_bitmap.png");draw_bitmap(bm);}
Since we use an unordered map, we must compute a hash value whenever we check for a bitmap resource. You will now see how we can optimize the runtime code by moving computations to compile time.
The advantages of the compile-time hash sum calculation
The problem we will try to solve is that every time the line get_bitmap_
resource is executed, the application will compute the hash
sum of the string "my_bitmap.png"
at runtime. We want to perform this calculation at compile time so that when the application executes, the hash sum has already been calculated. In other words, just as we have learned to use metaprogramming to generate functions and classes at compile time, we will now have it generate the hash sum at compile time.
Note: You might have already come to the ...