]> git.tdb.fi Git - libs/core.git/commitdiff
Store the value of the key in key_error
authorMikko Rasa <tdb@tdb.fi>
Sat, 1 Dec 2012 20:58:19 +0000 (22:58 +0200)
committerMikko Rasa <tdb@tdb.fi>
Sat, 1 Dec 2012 20:58:19 +0000 (22:58 +0200)
The type of the container is uninformative and often ugly.

source/core/maputils.cpp
source/core/maputils.h

index 4fcc8e2176769832b02f9d301810e1fd078fd9e0..28739f05ca86c59a3419e3d1f1f2dfe6c93539b7 100644 (file)
@@ -1,12 +1,14 @@
 #include <msp/debug/demangle.h>
 #include <msp/debug/demangle.h>
+#include <msp/strings/format.h>
 #include "maputils.h"
 
 using namespace std;
 
 namespace Msp {
 
 #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
 
 } // namespace Msp
index 9548714658d806fad41614357bc0e60fa8444cdf..8c642fb9c57a1f9acda6ba5ab2d0dc5311316306 100644 (file)
@@ -3,14 +3,48 @@
 
 #include <stdexcept>
 #include <typeinfo>
 
 #include <stdexcept>
 #include <typeinfo>
+#include <msp/strings/lexicalcast.h>
 
 namespace Msp {
 
 
 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<typename T>
+void operator<<(LexicalConverter &, const T &)
+{ }
+
+template<typename T>
+static std::string stringify_key(const T &k)
+{
+       try
+       {
+               LexicalConverter conv((Fmt()));
+               conv<<k;
+               return conv.get();
+       }
+       catch(const lexical_error &)
+       {
+               return "<cannot display value>";
+       }
+}
+
+} // namespace Internal
+
 class key_error: public std::runtime_error
 {
 public:
 class key_error: public std::runtime_error
 {
 public:
-       key_error(const std::type_info &);
-       ~key_error() throw() { }
+       template<typename T>
+       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())
 {
        typename T::iterator i = map.find(key);
        if(i==map.end())
-               throw key_error(typeid(T));
+               throw key_error(key);
 
        return i->second;
 }
 
        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())
 {
        typename T::const_iterator i = map.find(key);
        if(i==map.end())
-               throw key_error(typeid(T));
+               throw key_error(key);
 
        return i->second;
 }
 
        return i->second;
 }
@@ -38,7 +72,7 @@ template<typename T>
 const typename T::iterator insert_unique(T &map, const typename T::key_type &key, const typename T::mapped_type &item)
 {
        if(map.count(key))
 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;
 }
 
        return map.insert(typename T::value_type(key, item)).first;
 }