Proton  1.1.1
Make porting easy from Python to C++11
map.hpp
1 #ifndef PROTON_MAP_HEADER
2 #define PROTON_MAP_HEADER
3 
4 #include <map>
5 #include <iostream>
6 #include <stdexcept>
7 #include <proton/base.hpp>
8 #include <proton/pool.hpp>
9 #include <proton/ref.hpp>
10 
11 #include "_mapped_type.hpp"
12 
13 namespace proton{
14 
15 /** @addtogroup map_
16  * @{
17  */
18 
19 /** add an item in streaming style.
20  * @param x the map to be added
21  * @param item the new item
22  * @return the new x
23  */
24 template <typename _Key, typename _Tp, typename _Cmp, typename _Alloc>
25 std::map<_Key, _Tp, _Cmp, _Alloc>& operator<<(std::map<_Key, _Tp, _Cmp, _Alloc>& x,
26  const std::pair<const _Key, _Tp>& item)
27 {
28  x.insert(item);
29  return x;
30 }
31 
32 template <typename _Key, typename _Tp, typename _Cmp, typename _Alloc>
33 std::map<_Key, _Tp, _Cmp, _Alloc>& operator<<(std::map<_Key, _Tp, _Cmp, _Alloc>& x,
34  std::initializer_list<std::pair<const _Key, _Tp> > item)
35 {
36  x.insert(item);
37  return x;
38 }
39 
40 /** general output for map.
41  * @param s the output stream
42  * @param x the map to be outputed
43  * @return s
44  */
45 template <typename _Key, typename _Tp, typename _Cmp, typename _Alloc>
46 std::ostream& operator<<(std::ostream& s, const std::map<_Key, _Tp, _Cmp, _Alloc>& x)
47 {
48  s << "{";
49  bool first=true;
50  for(auto& t: x){
51  if(first)
52  first=false;
53  else
54  s <<", ";
55  s << t.first << " : "<<t.second;
56  }
57  s << "}";
58  return s;
59 }
60 
61 template <typename _Key, typename _Tp, typename _Cmp, typename _Alloc>
62 std::wostream& operator<<(std::wostream& s, const std::map<_Key, _Tp, _Cmp, _Alloc>& x)
63 {
64  s << L"{";
65  bool first=true;
66  for(auto& t: x){
67  if(first)
68  first=false;
69  else
70  s << L", ";
71  s << t.first << L" : "<<t.second;
72  }
73  s << L"}";
74  return s;
75 }
76 
77 /** a map extension implementing python's dict-like interfaces.
78  */
79 template <typename K, typename T, typename C=std::less<K>, typename A=smart_allocator<std::pair<const K,T> > >
80 class map_ : public std::map<K,T,C,A>{
81 public:
82  typedef std::map<K,T,C,A> baseT;
83  typedef std::pair<const K,T> itemT;
84 
85 public:
86  /** forwarding ctor.
87  */
88  template<typename ...argT> map_(argT&& ...a):baseT(a...)
89  {}
90 
91  /** initializer_list forwarding ctor.
92  */
93  map_(std::initializer_list<itemT> a):baseT(a)
94  {}
95 
96  /** copy ctor.
97  */
98  map_(const map_& x):baseT(x)
99  {}
100 
101  /** move ctor.
102  */
103  map_(map_&& x)noexcept:baseT(x)
104  {}
105 
106  explicit map_(const baseT& x):baseT(x)
107  {}
108 
109  map_(baseT&& x)noexcept:baseT(x)
110  {}
111 
112  /** assign.
113  */
114  map_& operator=(const map_& x)
115  {
116  baseT::operator=(x);
117  return *this;
118  }
119 
120  map_& operator=(map_&& x)noexcept
121  {
122  baseT::operator=(x);
123  return *this;
124  }
125 
126  map_& operator=(const baseT& x)
127  {
128  baseT::operator=(x);
129  return *this;
130  }
131 
132  map_& operator=(baseT&& x)noexcept
133  {
134  baseT::operator=(x);
135  return *this;
136  }
137 
138  template<typename argT> map_& operator=(argT&& a)
139  {
140  baseT::operator=(a);
141  return *this;
142  }
143 
144  map_& operator=(std::initializer_list<T> a)
145  {
146  baseT::operator=(a);
147  return *this;
148  }
149 
150  /** cast to std::set<>&.
151  */
152  operator baseT&()
153  {
154  return reinterpret_cast<baseT&>(*this);
155  }
156 
158 
159  /** remove an item.
160  * @param key the key.
161  * @throw std::out_of_range if there is no such a value.
162  */
163  void del(const K& key)
164  {
165  auto end=this->end();
166  auto it=this->find(key);
167  if(it==end)
168  throw std::out_of_range("The given key doesn't exist in this map.");
169  this->erase(it);
170  }
171 
172  /** get an item from the map.
173  * @param key the key of the item
174  * @return the corresponding value.
175  * @throw std::out_of_range if there is no such a key.
176  */
177  T get(const K& key)const
178  {
179  return this->at[key];
180  }
181 
182  /** get an item from the map.
183  * @param key the key of the item
184  * @param dft the default value
185  * @return the corresponding value, if the key doesn't exist, return the default.
186  */
187  template<typename ...D>
188  T get(const K& key, D&& ...dft)const
189  {
190  auto it=this->find(key);
191  if(it==this->end())
192  return T(dft...);
193  T r=it->second;
194  this->erase(it);
195  return r;
196  }
197 
198  /** deprecated, using has()
199  */
200  bool has_key(const K& key)const
201  {
202  return this->find(key)!=this->end();
203  }
204 
205  /** pop an item from the map.
206  * @param key the key of the item
207  * @return the corresponding value.
208  * @throw proton::err if there is no such a key.
209  */
210  T pop(const K& key)
211  {
212  auto it=this->find(key);
213  PROTON_THROW_IF(it==this->end(), "try to pop an non-existing key.");
214  T r=it->second;
215  this->erase(it);
216  return r;
217  }
218 
219  /** pop an item from the map.
220  * @param key the key of the item
221  * @param dft the default value
222  * @return the corresponding value, if the key doesn't exist, return the default.
223  */
224  template<typename ...D>
225  T pop(const K& key, D&& ...dft)
226  {
227  auto it=this->find(key);
228  if(it==this->end())
229  return T(dft...);
230  T r=it->second;
231  this->erase(it);
232  return r;
233  }
234 
235  /** pop the first item.
236  * @throw proton::err if there is no items in the map.
237  */
238  itemT popitem()
239  {
240  PROTON_THROW_IF(this->empty(), "try to pop an item from an empty map");
241  auto it=this->begin();
242  itemT r=*it;
243  this->erase(it);
244  return r;
245  }
246 
247  /** If key exists, return its value. If not, insert key with a value of default and return default.
248  */
249  template<typename ...D>
250  const T& setdefault(const K& key, D&&... dft)
251  {
252  auto it=this->find(key);
253  if(it!=this->end())
254  return it->second;
255  return this->insert(std::make_pair(key, T(dft...))).first->second;
256  }
257 
258  /** Update the map with the key/value pairs from other, overwriting existing keys.
259  */
260  template<typename oT>
261  void update(oT&& o)
262  {
263  for(auto i:o){
264  (*this)[i->first]=i->second;
265  }
266  }
267 };
268 
269 /**
270  * @example map.cpp
271  * [TODO]
272  */
273 
274 /** cast to proton::map_<>& from std::map<>&.
275  */
276 template<typename K, typename T, typename C, typename A>
277 map_<K,T,C,A>& cast_(std::map<K,T,C,A>& x)
278 {
279  return reinterpret_cast<map_<K,T,C,A>&>(x);
280 }
281 
282 template<typename K, typename T, typename C, typename A>
283 const map_<K,T,C,A>& cast_(const std::map<K,T,C,A>& x)
284 {
285  return reinterpret_cast<const map_<K,T,C,A>&>(x);
286 }
287 
288 template<typename K, typename T, typename C, typename A>
289 map_<K,T,C,A>&& cast_(std::map<K,T,C,A>&& x)
290 {
291  return reinterpret_cast<map_<K,T,C,A>&&>(x);
292 }
293 
294 template<typename K, typename T, typename C, typename A>
295 const map_<K,T,C,A>&& cast_(const std::map<K,T,C,A>&& x)
296 {
297  return reinterpret_cast<const map_<K,T,C,A>&&>(x);
298 }
299 
300 /**
301  * @}
302  */
303 
304 namespace detail{
305 
306 template<typename _Key, typename _Tp, typename _Cmp, typename _Alloc>
307 struct has_t<std::map<_Key, _Tp, _Cmp, _Alloc> >{
308  template<typename V> static bool result(const std::map<_Key, _Tp, _Cmp, _Alloc>& x, V&& v)
309  {
310  return x.find(v)!=x.end();
311  }
312 };
313 
314 template<typename _Key, typename _Tp, typename _Cmp, typename _Alloc>
315 struct has_t<map_<_Key, _Tp, _Cmp, _Alloc> >{
316  template<typename V> static bool result(const map_<_Key, _Tp, _Cmp, _Alloc>& x, V&& v)
317  {
318  return x.find(v)!=x.end();
319  }
320 };
321 
322 } // ns detail
323 
324 } // ns proton
325 
326 #endif // PROTON_MAP_HEADER