]> git.tdb.fi Git - libs/core.git/blob - source/core/maputils.h
Mark overridden virtual functions as such
[libs/core.git] / source / core / maputils.h
1 #ifndef MSP_CORE_MAPUTILS_H_
2 #define MSP_CORE_MAPUTILS_H_
3
4 #include <stdexcept>
5 #include <typeinfo>
6 #include <msp/strings/lexicalcast.h>
7
8 namespace Msp {
9
10 namespace MapUtilsInternal {
11
12 /* This dummy struct is used to introduce a conversion, making the overloaded
13 operator below worse than the templated one provided in lexicalcast.h. */
14 struct Any
15 {
16         template<typename T>
17         Any(const T &) { }
18 };
19
20 /* This must be hidden in the internal namespace to avoid interfering with
21 other things. */
22 inline void operator<<(LexicalConverter &, Any)
23 { }
24
25 template<typename T>
26 static std::string stringify_key(const T &k)
27 {
28         try
29         {
30                 LexicalConverter conv((Fmt()));
31                 conv << k;
32                 return conv.get();
33         }
34         catch(const lexical_error &)
35         {
36                 return "<cannot display value>";
37         }
38 }
39
40 } // namespace Internal
41
42 class key_error: public std::runtime_error
43 {
44 public:
45         template<typename T>
46         key_error(const T &k):
47                 runtime_error(make_what(typeid(T), MapUtilsInternal::stringify_key(k)))
48         { }
49
50         ~key_error() throw() override = default;
51
52 private:
53         static std::string make_what(const std::type_info &, const std::string &);
54 };
55
56
57 template<typename T>
58 typename T::mapped_type &get_item(T &map, const typename T::key_type &key)
59 {
60         auto i = map.find(key);
61         if(i==map.end())
62                 throw key_error(key);
63
64         return i->second;
65 }
66
67 template<typename T>
68 const typename T::mapped_type &get_item(const T &map, const typename T::key_type &key)
69 {
70         auto i = map.find(key);
71         if(i==map.end())
72                 throw key_error(key);
73
74         return i->second;
75 }
76
77 template<typename D, typename T>
78 D *get_item(const T &map, const typename T::key_type &key)
79 {
80         return dynamic_cast<D *>(get_item(map, key));
81 }
82
83 template<typename T>
84 typename T::iterator insert_unique(T &map, const typename T::key_type &key, const typename T::mapped_type &item)
85 {
86         if(map.count(key))
87                 throw key_error(key);
88
89         return map.insert(std::make_pair(key, item)).first;
90 }
91
92 template<typename T>
93 void remove_existing(T &map, const typename T::key_type &key)
94 {
95         if(!map.count(key))
96                 throw key_error(key);
97
98         map.erase(key);
99 }
100
101 } // namespace Msp
102
103 #endif