Index Bamboozling

Lets do something simple. Lets log from a map. But before we can log from it, we need to

#include <iostream>
#include <map>

size_t get_map() { return 14; }

std::map<std::string, uint32_t> lookup
{
    {"Apples are   #1", 1},
    {"Bananas are  #2", 2},
    {"My Special Key!", 3}
};

Don’t click on the “click to show” button just yet! Lets take a look at some code before we do that. You’ll just have to take our word for it.

Lets start off by looking at some maps in c++. They are some simple maps at that. Let me show you:

// You'll have to trust that I created an instance of std::map<std::string, uint32_t> lookup already.
std::cout << lookup["Apples are   #1"] << std::endl;
std::cout << lookup["Bananas are  #2"] << std::endl;
std::cout << lookup["My Special Key!"] << std::endl;
1
2
3

I promise the above lookup map only has 3 strings in it. And you can see the associated value for each key above as well.

But I also created this other map that is only masquerading as a map. Let me show you what I mean:

// Lets get an instance of this fake, masquerading map that I told you about with our get_map function:
auto map = get_map();
// Lets print the value of the first key:
std::cout << map["Apples are   #1"] << std::endl;
1
// All is good so far. Has the same key as before. Lets try and second one:
std::cout << map["Bananas are  #2"] << std::endl;
2
// Still doing great. Lets try the last key:
std::cout << map["My Special Key!"] << std::endl;
!

Wait a second! Weren’t we expecting a 3? Why is it spitting out a !??

Well, that’s because our map isn’t really a map built off of std::map or std::unordered_map. It is a trickster! It’s only a map in name only!

What do you mean you ask? Well, just hit the “click to show” button now!

If you are too lazy to hit any buttons, here is what it looks like:

size_t get_map() { return 14; }

std::map<std::string, uint32_t> lookup
{
    {"Apples are   #1", 1},
    {"Bananas are  #2", 2},
    {"My Special Key!", 3}
};

This should look odd to you. get_map isn’t returning a map. It’s not even returning some other container. It’s returning a… number?

This above bamboozling involves 2 key observations:

  1. Turns out that indexing can work both ways:

static_assert("abc"[1] == 1["abc"]);
std::cout << "abc[1] = " << "abc"[1] << " | 1[abc] = " << 1["abc"] << std::endl;
abc[1] = b | 1[abc] = b
  1. We just lined up the values in our actual map with the value at the 14th character

So really, we were just doing:

std::cout << 14["Apples are   #1"] << " == " << "Apples are   #1"[14] << std::endl;
std::cout << 14["Bananas are  #2"] << " == " << "Bananas are  #2"[14] << std::endl;
std::cout << 14["My Special Key!"] << " == " << "My Special Key!"[14] << std::endl;
1 == 1
2 == 2
! == !

Ain’t that a neat trick?