The Standard Template Library
std::map[]
operator will create and return a new entry if passed a key that does not already exist in the map.
This means that you cannot use this operator when you do
not want to create a new entry (i.e., you expect the key-value pair to already exist in the map), or in a
const
context (i.e., in a
const
method or when using a
const
object).
Instead, in these situations, you need to first pull a (
const
) iterator using
std::map.find()
, and then check to see if its value equals
std::map.end()
, and only if not proceed with referencing the result.
This means that instead of, for example:
double v = split_lengths[s];
You need to:
std::map::const_iterator it = split_lengths.find(s);
if (it != split_lengths.end()) {
// do what you want ... finally!
} else {
// raise exception
}
Yup. This is a pain.
Victorian kitchen cooking, indeed.
The new C++0x supplies an
std::map.at()
method, which throws a
std::out_of_range
exception if the value is not found.
If I am going to still be programming in C++ in a couple of decades when this version becomes widespread enough, that would be the way to go. In the meantime, however, the following template makes life a little easier:
template
const typename T::value_type::second_type& map_at(const T& container,
const typename T::value_type::first_type key) {
typename T::const_iterator it = container.find(key);
if (it == container.end()) {
throw std::out_of_range("Key not found");
}
return it->second;
}
Now a safe yet succint (in C++/STL terms) way of getting items out of a map is:
double v = map_at(split_lengths, s);
Bringing the
Victorian kitchen into the Edwardian era one new-fangled gadget at a time.