X-Git-Url: http://git.tdb.fi/?p=libs%2Fcore.git;a=blobdiff_plain;f=source%2Fcore%2Fmaputils.h;h=f5faa1271a2e1317523767c5e9c3e6a858792027;hp=1a7c0ae6ce8e952d1ab9b10113e47172dc4b3136;hb=f24e7b96e76b63c9b9b8a6bce4c7a9db64276ea8;hpb=9519381422961a538a3ebbd1e6563d170215f14e diff --git a/source/core/maputils.h b/source/core/maputils.h index 1a7c0ae..f5faa12 100644 --- a/source/core/maputils.h +++ b/source/core/maputils.h @@ -3,22 +3,63 @@ #include #include +#include namespace Msp { +namespace MapUtilsInternal { + +/* This dummy struct is used to introduce a conversion, making the overloaded +operator below worse than the templated one provided in lexicalcast.h. */ +struct Any +{ + template + Any(const T &) { } +}; + +/* This must be hidden in the internal namespace to avoid interfering with +other things. */ +inline void operator<<(LexicalConverter &, Any) +{ } + +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 &); + 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 &); }; template typename T::mapped_type &get_item(T &map, const typename T::key_type &key) { - typename T::iterator i = map.find(key); + auto i = map.find(key); if(i==map.end()) - throw key_error(typeid(T)); + throw key_error(key); return i->second; } @@ -26,13 +67,37 @@ typename T::mapped_type &get_item(T &map, const typename T::key_type &key) template const typename T::mapped_type &get_item(const T &map, const typename T::key_type &key) { - typename T::const_iterator i = map.find(key); + auto i = map.find(key); if(i==map.end()) - throw key_error(typeid(T)); + throw key_error(key); return i->second; } +template +D *get_item(const T &map, const typename T::key_type &key) +{ + return dynamic_cast(get_item(map, key)); +} + +template +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(key); + + return map.insert(std::make_pair(key, item)).first; +} + +template +void remove_existing(T &map, const typename T::key_type &key) +{ + if(!map.count(key)) + throw key_error(key); + + map.erase(key); +} + } // namespace Msp #endif