#include <iostream>
#include <map>
#include <stdexcept>

template <typename K, typename V>
V& map_at(std::map<K, V>& a_map, K const& a_key)
{
    typename std::map<K, V>::iterator i = a_map.find(a_key);
    if (a_map.end() == i)
    {
        throw std::out_of_range("map_at()");
    }
    return i->second;
}

int main()
{
    try
    {
        std::map<int, int> m;
        m[4] = 4;
        std::cout << map_at(m, 4) << std::endl;
        map_at(m, 5);
    }
    catch (std::out_of_range const& e)
    {
        std::cout << "out_of_range: " << e.what() << std::endl;
    }

    try
    {
        std::map<std::string, char> m;
        m["hello"] = 'c';
        std::cout << map_at(m, std::string("hello")) << std::endl;
        map_at(m, std::string("world"));
    }
    catch (std::out_of_range const& e)
    {
        std::cout << "out_of_range: " << e.what() << std::endl;
    }

    return 0;
}
