From 1e0abc3a49ade6a4fa1b38f744df070c40a87724 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Sat, 1 Dec 2012 22:58:19 +0200 Subject: [PATCH] Store the value of the key in key_error The type of the container is uninformative and often ugly. --- source/core/maputils.cpp | 8 +++++--- source/core/maputils.h | 44 +++++++++++++++++++++++++++++++++++----- 2 files changed, 44 insertions(+), 8 deletions(-) diff --git a/source/core/maputils.cpp b/source/core/maputils.cpp index 4fcc8e2..28739f0 100644 --- a/source/core/maputils.cpp +++ b/source/core/maputils.cpp @@ -1,12 +1,14 @@ #include +#include #include "maputils.h" using namespace std; namespace Msp { -key_error::key_error(const type_info &t): - runtime_error(Debug::demangle(t.name())) -{ } +string key_error::make_what(const type_info &type, const string &value) +{ + return format("%s(%s)", Debug::demangle(type.name()), value); +} } // namespace Msp diff --git a/source/core/maputils.h b/source/core/maputils.h index 9548714..8c642fb 100644 --- a/source/core/maputils.h +++ b/source/core/maputils.h @@ -3,14 +3,48 @@ #include #include +#include namespace Msp { +namespace MapUtilsInternal { + +/* This must be hidden in the internal namespace to avoid interfering with +other things. There may be problems if a key type has operator<< for ostream +but not LexicalConverter. */ +template +void operator<<(LexicalConverter &, const T &) +{ } + +template +static std::string stringify_key(const T &k) +{ + try + { + LexicalConverter conv((Fmt())); + conv<"; + } +} + +} // namespace Internal + class key_error: public std::runtime_error { public: - key_error(const std::type_info &); - ~key_error() throw() { } + template + key_error(const T &k): + runtime_error(make_what(typeid(T), MapUtilsInternal::stringify_key(k))) + { } + + virtual ~key_error() throw() { } + +private: + static std::string make_what(const std::type_info &, const std::string &); }; @@ -19,7 +53,7 @@ typename T::mapped_type &get_item(T &map, const typename T::key_type &key) { typename T::iterator i = map.find(key); if(i==map.end()) - throw key_error(typeid(T)); + throw key_error(key); return i->second; } @@ -29,7 +63,7 @@ const typename T::mapped_type &get_item(const T &map, const typename T::key_type { typename T::const_iterator i = map.find(key); if(i==map.end()) - throw key_error(typeid(T)); + throw key_error(key); return i->second; } @@ -38,7 +72,7 @@ template const typename T::iterator insert_unique(T &map, const typename T::key_type &key, const typename T::mapped_type &item) { if(map.count(key)) - throw key_error(typeid(T)); + throw key_error(key); return map.insert(typename T::value_type(key, item)).first; } -- 2.45.2