0 votes
#include <fstream>
#include <iostream>
#include <map>

int main(int argc, char** argv) {
    try {
        std::map<std::string, int> m{{"a", 1}, {"b", 2}};
        std::cout <<"c") << std::endl;
    } catch (const std::exception& e) {
        std::cerr << e.what() << std::endl;

    return 0;
In C++, when retrieving a non-existent key of a map, the exception looks like map::at:  key not found. Information about what the key is is not provided.

Also, if one is accessing a non-existent file, the exception message of std::ios_base::failure looks like ios_base::clear: unspecified iostream_category error. The filename which caused the exception is not provided. Thus it may take quite a time to find out where the exception is from if there are many or ifstream is uses in a project.

In contrast to this, Python may tell you KeyError: 'c' or FileNotFoundError: [Errno 2] No such file or directory: 'foo'.
asked Dec 30, 2017 in C++ by Amrendra | 31 views

2 Answers

0 votes
The issue is the C++ object model, which differs from Python's. To contrast, first let's answer: what does Python store in the exception object to print the key? It's a reference that keeps that object alive.

This cannot be done simply in C++.

std::out_of_range can't store a pointer or reference to the key as is. The handler for the exception may be in far away block. And that means that the key most probably went out of scope before the handler is entered. We get undefined behavior if the key is referred to.

std::out_of_range is a concrete class. Not a template like std::map. It can't easily copy the key into itself. There are many different Key types, and it obviously can't account for all of them. Even if it could, what if the key is extremely expensive to copy? Or even non-copyable at all? Even in cases where that's not true, what if the key isn't convertible to a string, or printable?

The above points don't mean it's impossible. std::map::at can throw a sub-class of std::out_of_range that does type erasure and so forth. But I hope you see it has non-trivial overhead. C++ is all about not paying in performance for features you don't need or use. Making everyone bear that overhead unconditionally isn't in line with this design.
answered Dec 30, 2017 by Amrendra
0 votes
C++ standard specifies that map::at(const key_type& k) will launch a std::out_of_range exception (if value is not inside it); nothing more... but nothing less; a particular implementation of map::at() but the problem would be that the k's key_type have to be converted to char*. So there are several options:

Do not show this information
std::map does not store types without (at least implicit) conversion to char*: but there would be a requirement applied to the key_store type that is not strict necessary
To provide different messages in std::out_of_range exception depending on the key_type: but this solution does not always show the expected information
In other point of view, std::out_of_range inherits from std::logic_error; C++ standard distinguishes between two main types of exceptions:

logic_error: they are due to errors in the internal logic of the program. In theory, they are preventable.
runtime_error: they are due to events beyond the scope of the program. They cannot be easily predicted in advance.
In our case, we can check the existence of an element easily (so our case fixes with this case)
answered Dec 30, 2017 by Amrendra

Related Questions

Welcome to Knowledge Boostr, where you can ask questions and receive answers from other members of the community.
This is a collaboratively edited question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top Q&A for professional and enthusiast programmers Q&A for professional and enthusiast programmers Q&A for professional and enthusiast programmers Q&A for professional and enthusiast programmers

23,494 questions
40,169 answers
23,610 users