Honeycomb  0.1
Component-Model Framework
MtMap.h
Go to the documentation of this file.
1 // Honeycomb, Copyright (C) 2015 NewGamePlus Inc. Distributed under the Boost Software License v1.0.
2 #pragma once
3 
4 #include "Honey/String/Id.h"
5 #include "Honey/Misc/Optional.h"
6 
7 namespace honey
8 {
9 
11 
28 
31 
32 template<class Key_, class Val_, class List_> class MtMapElem;
35 
37 namespace priv
38 {
39  template<class... Pairs> struct MtMap_ { typedef MtMapTail type; };
40  template<class Val, class Key, class... Pairs>
41  struct MtMap_<Val, Key, Pairs...> { typedef MtMapElem<Key, Val, typename MtMap_<Pairs...>::type> type; };
42 }
45 template<class... Pairs> using MtMap = typename priv::MtMap_<Pairs...>::type;
47 
49 template<class Key_, class Val_>
50 struct MtPair
51 {
52  typedef Key_ Key;
53  typedef Val_ Val;
54 
55  template<class Val>
56  MtPair(Val&& val) : key(), val(forward<Val>(val)) {}
57 
58  const Key key;
59  Val val;
60 };
61 
63 #define mtkey(Name) \
64  struct Name \
65  { \
66  \
67  static mt_global(const Id, id, (#Name)); \
68  \
69  template<class Val> MtPair<Name, Val> operator=(Val&& val) \
70  { return MtPair<Name, Val>(forward<Val>(val)); } \
71  }; \
72 
73 #define mtkeygen(Name) \
75  template<szt Index> struct Name \
76  { \
77  static mt_global(const Id, id, (sout() << #Name << "<" << Index << ">")); \
78  template<class Val> MtPair<Name, Val> operator=(Val&& val) \
79  { return MtPair<Name, Val>(forward<Val>(val)); } \
80  }; \
81 
82 
83 namespace priv
84 {
85  template<class... Pairs> struct PairSeq {};
86 
87  template<class... Pairs> struct PairSeqGen_ : PairSeqGen_<PairSeq<>, Pairs...> {};
88  template<class... Seq, class Key, class Val, class... Pairs>
89  struct PairSeqGen_<PairSeq<Seq...>, MtPair<Key, Val>, Pairs...> : PairSeqGen_<PairSeq<Seq..., Val, Key>, Pairs...> {};
90  template<class... Seq>
91  struct PairSeqGen_<PairSeq<Seq...>> { typedef PairSeq<Seq...> type; };
92 
94  template<class... Pairs> using PairSeqGen = typename PairSeqGen_<Pairs...>::type;
95 
96  template<class... Seq, class... Pairs>
97  MtMap<Seq...> mtmap_(PairSeq<Seq...>, Pairs&&... pairs) { return MtMap<Seq...>(mt::tag<0>(), forward<Pairs>(pairs)...); }
98 }
101 template<class... Pairs>
103 auto mtmap(Pairs&&... pairs) ->
104  decltype(priv::mtmap_(priv::PairSeqGen<Pairs...>(), forward<Pairs>(pairs)...))
105 { return priv::mtmap_(priv::PairSeqGen<Pairs...>(), forward<Pairs>(pairs)...); }
106 
108 
112 template<class Head, class Elem = Head>
114 {
115  friend class MtMapIter;
116 
117  typedef typename Elem::Key Key;
118  typedef typename Elem::Val Val;
119  typedef typename Head::Super::template findElem<Key>::Next Next;
120  typedef typename Head::Super::template findElem<Key>::Prev Prev;
121 
122 public:
123  // Propogate const to pair value
124  typedef MtPair<Key, decltype(declval<Head>().get(Key()))> Pair;
125 
126  MtMapIter(Head& head) : _head(&head), pair(_head->get(Key())) {}
127 
129  NextIter operator++() { return NextIter(*_head); }
131  PrevIter operator--() { return PrevIter(*_head); }
132 
133  template<class Iter> bool operator==(const Iter& rhs) const { return _head == rhs._head && std::is_same<typename Pair::Key, typename Iter::Pair::Key>::value; }
134  template<class Iter> bool operator!=(const Iter& rhs) const { return !operator==(rhs); }
135 
136  const Pair& operator*() const { return pair; }
137  Pair& operator*() { return pair; }
138  const Pair* operator->() const { return &pair; }
139  Pair* operator->() { return &pair; }
140 
141 private:
142  Head* _head;
143  Pair pair;
144 };
145 
146 
148 namespace priv
149 {
151  template<class Iter, class Func, typename std::enable_if<mt::isCallable<Func, typename Iter::Pair::Key, typename Iter::Pair::Val&>::value, int>::type=0>
152  void for_each_mtmap_call(Iter& it, Func&& func) { func(it->key, it->val); }
153  template<class Iter, class Func, typename mt::disable_if<mt::isCallable<Func, typename Iter::Pair::Key, typename Iter::Pair::Val&>::value, int>::type=0>
154  void for_each_mtmap_call(Iter&, Func&&) {}
155 }
157 template<class Iter1, class Iter2, class Func>
158 auto for_each_mtmap(Iter1, Iter2, Func&&) ->
159  typename mt::disable_if<!std::is_same<typename Iter1::Pair::Key, typename Iter2::Pair::Key>::value>::type {}
162 template<class Iter1, class Iter2, class Func>
164 auto for_each_mtmap(Iter1 itBegin, Iter2 itEnd, Func&& func) ->
165  typename std::enable_if<!std::is_same<typename Iter1::Pair::Key, typename Iter2::Pair::Key>::value>::type
166 {
167  priv::for_each_mtmap_call(itBegin, func);
168  for_each_mtmap(++itBegin, itEnd, forward<Func>(func));
169 }
170 
171 
173 namespace priv
174 {
176  template<class Val> struct isOptional : std::false_type {};
177  template<class Val> struct isOptional<optional<Val>> : std::true_type {};
178  template<> struct isOptional<mt::Void> : std::true_type {};
179 
181  struct MtMapToString
182  {
183  MtMapToString(ostream& os) : os(os), count(0) {}
184  template<class Key, class Val>
185  void operator()(Key, const Val& val)
186  {
187  if (count++ > 0) os << ", ";
188  os << Key::id() << ": " << val;
189  }
190  ostream& os;
191  szt count;
192  };
193 }
196 template<class Subclass, class Key_, class Val_, class List_>
199 {
200  template<class, class, class, class> friend class MtMapCommon;
201  template<class, class> friend class MtMapIter;
202 
203 public:
204  typedef Key_ Key;
205  typedef Val_ Val;
206  typedef List_ List;
207 
208 private:
209  static const bool isTail = std::is_same<List, mt::Void>::value;
210 
212  template<bool isTail, szt _=0>
213  struct priv
214  {
216  template<class Key, class Prev>
217  struct findElem : List::Super::template findElem<Key, Subclass> {};
218 
220  template<class Prev_>
221  struct findElem<Key, Prev_>
222  {
223  typedef Subclass type;
224  typedef Prev_ Prev;
225  typedef List Next;
226  };
227 
229  template<szt Count> struct sizeR : List::Super::template sizeR<Count+1> {};
230  };
231 
233  template<szt _>
234  struct priv<true,_>
235  {
236  // Fallback for any key
237  template<class Key, class Prev_>
238  struct findElem
239  {
240  typedef Subclass type;
241  typedef Prev_ Prev;
242  typedef Subclass Next;
243  };
244 
246  template<szt Count> struct sizeR : mt::Value<szt, Count> {};
247  };
248 
250  template<class Key, class Prev = Subclass>
251  struct findElem : priv<isTail>::template findElem<Key, Prev> {};
252 
254  template<szt Count>
255  struct sizeR : priv<isTail>::template sizeR<Count> {};
256 
257 public:
259  template<class Key> struct hasKey_ : mt::Value<bool, !std::is_same<typename findElem<Key>::type, MtMapTail>::value> {};
261  template<class Key> bool hasKey(Key) const { return hasKey_<Key>::value; }
262 
264  template<class Key> using getResult = typename findElem<Key>::type::Val;
265 
269 
271  beginResult begin() { return beginResult(subc()); }
272  beginResult_const begin() const { return beginResult_const(subc()); }
273 
277 
279  endResult end() { return endResult(subc()); }
280  endResult_const end() const { return endResult_const(subc()); }
281 
285 
287  template<class Key>
288  iterResult<Key> iter(Key) { return iterResult<Key>(subc()); }
289  template<class Key>
290  iterResult_const<Key> iter(Key) const { return iterResult_const<Key>(subc()); }
291 
292 private:
293  template<class... Pairs> struct insertResult_ { typedef Subclass type; };
294  template<class Val, class Key, class... Pairs>
295  struct insertResult_<Val, Key, Pairs...>
296  {
297  static_assert(!hasKey_<Key>::value, "Insert failed. Key already exists.");
298  typedef MtMapElem<Key, Val, typename insertResult_<Pairs...>::type> type;
299  };
300 
301  template<class PairSeq, class... Pairs> struct insertResult_seq;
302  template<class... Seq, class... Pairs>
303  struct insertResult_seq<honey::priv::PairSeq<Seq...>, Pairs...> { typedef typename insertResult_<Seq...>::type type; };
304 
305 public:
307  template<class... Pairs> using insertResult = typename insertResult_<Pairs...>::type;
308 
310  template<class... Pairs>
311  typename insertResult_seq<honey::priv::PairSeqGen<Pairs...>, Pairs...>::type
312  insert(Pairs&&... pairs) const { return typename insertResult_seq<honey::priv::PairSeqGen<Pairs...>, Pairs...>::type(mt::tag<1>(), subc(), forward<Pairs>(pairs)...); }
313 
314 private:
315  template<bool isTail, class... Keys>
316  struct eraseResult_
317  {
318  typedef typename std::conditional<
319  mt::typeIndex<Key, Keys...>::value >= 0,
320  typename List::Super::template eraseResult_<List::Super::isTail, Keys...>::type,
321  MtMapElem<Key, Val, typename List::Super::template eraseResult_<List::Super::isTail, Keys...>::type>
322  >::type type;
323  };
324  template<class... Keys>
325  struct eraseResult_<true, Keys...> { typedef MtMapTail type; };
326 
327  template<class _=void> struct clearResult_ { typedef MtMapTail type; };
328 
329 public:
331  template<class... Keys> using eraseResult = typename eraseResult_<isTail, Keys...>::type;
332 
334  template<class... Keys>
335  eraseResult<Keys...> erase(Keys...) const { return eraseResult<Keys...>(subc()); }
336 
338  typedef typename clearResult_<>::type clearResult;
340  clearResult clear() { return clearResult(); }
341 
343  struct size_ : sizeR<0> {};
345  szt size() const { return size_::value; };
346 
348  struct empty_ : mt::Value<bool, isTail> {};
350  bool empty() const { return empty_::value; }
351 
352  friend ostream& operator<<(ostream& os, const Subclass& map)
353  { os << "{ "; for_each_mtmap(map.begin(), map.end(), honey::priv::MtMapToString(os)); os << " }"; return os; }
354 
355 private:
357  const Subclass& subc() const { return static_cast<const Subclass&>(*this); }
358  Subclass& subc() { return static_cast<Subclass&>(*this); }
359 };
360 
362 
366 template<class Key_, class Val_, class List_>
367 class MtMapElem : public MtMapCommon<MtMapElem<Key_,Val_,List_>, Key_, Val_, List_>, public List_
368 {
369  template<class, class, class, class> friend class MtMapCommon;
370  template<class, class, class> friend class MtMapElem;
371  template<class, class> friend class MtMapIter;
373 
374 public:
375  using typename Super::Key;
376  using typename Super::Val;
377  using typename Super::List;
378  template<class Key> using hasKey_ = typename Super::template hasKey_<Key>;
379  using Super::hasKey;
380  template<class Key> using getResult = typename Super::template getResult<Key>;
381  using typename Super::beginResult;
382  using typename Super::beginResult_const;
383  using Super::begin;
384  using typename Super::endResult;
385  using typename Super::endResult_const;
386  using Super::end;
387  template<class Key> using iterResult = typename Super::template iterResult<Key>;
388  template<class Key> using iterResult_const = typename Super::template iterResult_const<Key>;
389  using Super::iter;
390  template<class... Pairs> using insertResult = typename Super::template insertResult<Pairs...>;
391  using Super::insert;
392  template<class... Keys> using eraseResult = typename Super::template eraseResult<Keys...>;
393  using Super::erase;
394  using typename Super::clearResult;
395  using Super::clear;
396  using typename Super::size_;
397  using Super::size;
398  using typename Super::empty_;
399  using Super::empty;
400 
401  MtMapElem() { static_assert(honey::priv::isOptional<Val>::value, "Key not optional. Must provide key to constructor."); }
402 
404  template<class Pair, class... Pairs>
405  MtMapElem(mt::tag<0>, Pair&& pair, Pairs&&... pairs) :
406  List(mt::tag<0>(), forward<Pairs>(pairs)...),
407  _val(forward<typename Pair::Val>(pair.val))
408  { static_assert(std::is_same<Key,typename Pair::Key>::value, "Ctor failed. Key mismatch. Wrong init order."); }
409 
411  template<class Map>
412  MtMapElem(Map&& map) : List(forward<Map>(map)), _val(priv<Map>::init(map.get(Key()))) {}
413 
415  template<class Map>
416  MtMapElem& operator=(Map&& rhs) { priv<Map>::assign(_val, rhs.get(Key())); List::operator=(forward<Map>(rhs)); return *this; }
417 
418  using List::operator[];
420  const Val& operator[](Key) const { return _val; }
421  Val& operator[](Key) { return _val; }
422 
423  using List::get;
425  const Val& get(Key) const { return _val; }
426  Val& get(Key) { return _val; }
427 
428  using List::set;
430  template<class Val>
431  bool set(MtPair<Key, Val>&& pair) { _val = forward<Val>(pair.val); return true; }
432 
434  template<class Map>
435  void setDefaults(Map&& defaults) { priv<Map>::setDefault(_val, defaults.get(Key())); List::setDefaults(forward<Map>(defaults)); }
436 
437 private:
438  template<class Map>
439  struct priv
440  {
441  typedef typename mt::removeRef<Map>::type Map_;
442 
443  static const bool movable = !mt::isLref<Map>::value && !mt::isLref<typename Map_::template getResult<Key>>::value;
444  static const bool optional = honey::priv::isOptional<Val>::value;
445 
446  template<class T>
447  static auto init(T&& val) -> typename std::enable_if<mt::True<T>::value && movable, decltype(move(val))>::type { return move(val); }
448  template<class T>
449  static auto init(T&& val) -> typename mt::disable_if<mt::True<T>::value && movable, T&>::type { return val; }
450  static Val init(mt::Void)
451  {
452  static_assert(optional, "Key not optional. Must provide key to constructor.");
453  return Val();
454  }
455 
456  template<class T>
457  static auto assign(Val& lhs, T&& rhs) -> typename std::enable_if<mt::True<T>::value && movable>::type { lhs = move(rhs); }
458  template<class T>
459  static auto assign(Val& lhs, T&& rhs) -> typename mt::disable_if<mt::True<T>::value && movable>::type { lhs = rhs; }
460  static void assign(Val&, mt::Void){}
461 
462  template<class T>
463  static auto setDefault(Val& lhs, T&& rhs) -> typename std::enable_if<mt::True<T>::value && optional>::type { if (!lhs) lhs = rhs(); }
464  template<class T>
465  static auto setDefault(Val&, T&&) -> typename mt::disable_if<mt::True<T>::value && optional>::type {}
466  static void setDefault(Val&, mt::Void) {}
467  };
468 
470  template<class Map, class Pair, class... Pairs>
471  MtMapElem(mt::tag<1>, const Map& map, Pair&& pair, Pairs&&... pairs) :
472  List(mt::tag<1>(), map, forward<Pairs>(pairs)...),
473  _val(forward<typename Pair::Val>(pair.val)) {}
474 
475  template<class Map, class Pair>
476  MtMapElem(mt::tag<1>, const Map& map, Pair&& pair) :
477  List(map),
478  _val(forward<typename Pair::Val>(pair.val)) {}
479 
481  Val _val;
482 };
483 
485 template<>
487 class MtMapElem<mt::Void, mt::Void, mt::Void> : public MtMapCommon<MtMapTail, mt::Void, mt::Void, mt::Void>
488 {
489  template<class, class, class, class> friend class MtMapCommon;
490  template<class, class, class> friend class MtMapElem;
491  template<class, class> friend class MtMapIter;
492  typedef MtMapCommon<MtMapElem, Key, Val, List> Super;
493 
494 public:
495  MtMapElem() {}
497  template<class Map> MtMapElem(Map&&) {}
499  template<class Map> MtMapElem& operator=(Map&&) { return *this; }
501  template<class Key> Val operator[](Key) const { return Val(); }
502  template<class Key> Val operator[](Key) { return Val(); }
504  template<class Key> Val get(Key) const { return Val(); }
505  template<class Key> Val get(Key) { return Val(); }
507  template<class Key, class Val>
508  bool set(MtPair<Key, Val>&&) { return false; }
510  template<class Map> void setDefaults(Map&&) {}
511 
512 private:
514  MtMapElem(mt::tag<0>) {}
515 };
518 
520 }
priv::typeIndex< 0, Match, Ts... > typeIndex
Get index of first matching type in parameter pack, returns -1 if not found.
Definition: Meta.h:108
Pair * operator->()
Definition: MtMap.h:139
beginResult_const begin() const
Definition: MtMap.h:272
MtMapElem(mt::tag< 0 >, Pair &&pair, Pairs &&...pairs)
Ctor, pairs must be in correct order.
Definition: MtMap.h:405
friend class MtMapCommon
Definition: MtMap.h:369
NextIter operator++()
Definition: MtMap.h:129
iterResult_const< Key > iter(Key) const
Definition: MtMap.h:290
Key_ Key
Key type.
Definition: MtMap.h:204
We don't have this key, recurse towards tail.
Definition: MtMap.h:217
typename findElem< Key >::type::Val getResult
Result type of get()
Definition: MtMap.h:264
Value< bool, std::is_lvalue_reference< T >::value > isLref
Check if type is an lvalue reference.
Definition: Meta.h:53
MtMapElem & operator=(Map &&rhs)
Copy/Move-assign any map type. Assign to matching key in other map, recurse to tail.
Definition: MtMap.h:416
endResult end()
Get end of an iterator over keys and values of this map.
Definition: MtMap.h:279
friend ostream & operator<<(ostream &os, const Subclass &map)
Definition: MtMap.h:352
const Pair * operator->() const
Definition: MtMap.h:138
clearResult_::type clearResult
Result type of clear()
Definition: MtMap.h:338
MtMapIter< Head, Prev > PrevIter
Definition: MtMap.h:130
typename Super::template hasKey_< Key > hasKey_
Definition: MtMap.h:378
Map element in recursive list.
Definition: MtMap.h:32
MtMapIter< const Subclass, MtMapTail > endResult_const
Definition: MtMap.h:276
Get size of map at compile-time.
Definition: MtMap.h:343
bool operator==(const Iter &rhs) const
Definition: MtMap.h:133
bool set(MtPair< Key, Val > &&pair)
Set value at key from the pair (key() = value). Returns false if the key isn't found.
Definition: MtMap.h:431
Val_ Val
Value type.
Definition: MtMap.h:205
iterResult< Key > iter(Key)
Get iterator to element by key.
Definition: MtMap.h:288
std::integral_constant< T, val > Value
Holds a constant integral value.
Definition: Meta.h:29
szt size() const
Get size of map.
Definition: MtMap.h:345
const Val & get(Key) const
Get value at key.
Definition: MtMap.h:425
Subclass type
Definition: MtMap.h:240
std::remove_reference< T > removeRef
Remove reference from type.
Definition: Meta.h:44
Key_ Key
Definition: MtMap.h:52
Val & operator[](Key)
Definition: MtMap.h:421
static auto _
Definition: Module.cpp:8
Val_ Val
Definition: MtMap.h:53
MtPair(Val &&val)
Definition: MtMap.h:56
beginResult begin()
Get beginning of an iterator over keys and values of this map.
Definition: MtMap.h:271
Bidirectional iterator over map key/value pairs.
Definition: MtMap.h:113
bool empty() const
Check if empty.
Definition: MtMap.h:350
typename insertResult_< Pairs... >::type insertResult
Result type of insert(). New pairs are inserted at the front.
Definition: MtMap.h:307
auto mtmap(Pairs &&...pairs) -> decltype(priv::mtmap_(priv::PairSeqGen< Pairs... >(), forward< Pairs >(pairs)...))
Construct a map from (key() = value) pairs.
Definition: MtMap.h:103
typename eraseResult_< isTail, Keys... >::type eraseResult
Result type of erase(). Reconstructs type without matching keys.
Definition: MtMap.h:331
Pair & operator*()
Definition: MtMap.h:137
auto for_each_mtmap(Iter1 itBegin, Iter2 itEnd, Func &&func) -> typename std::enable_if<!std::is_same< typename Iter1::Pair::Key, typename Iter2::Pair::Key >::value >::type
Iterate over map calling functor (visitor) for each key/value pair.
Definition: MtMap.h:164
MtMapIter< Head, Next > NextIter
Definition: MtMap.h:128
MtMapIter(Head &head)
Definition: MtMap.h:126
MtMapElem()
Definition: MtMap.h:401
MtMapIter< Subclass, MtMapTail > endResult
Result type of end()
Definition: MtMap.h:275
Val val
Definition: MtMap.h:59
const Val & operator[](Key) const
Get value at key.
Definition: MtMap.h:420
typename Super::template insertResult< Pairs... > insertResult
Definition: MtMap.h:390
Subclass Next
Definition: MtMap.h:242
Recurse to tail.
Definition: MtMap.h:229
MtMapIter< const Subclass > beginResult_const
Definition: MtMap.h:268
List_ List
Rest of map.
Definition: MtMap.h:206
Use to differentiate an overloaded function by type. Accepts dummy parameter default value: func(tag<...
Definition: Meta.h:39
size_t szt
Size type, shorthand for size_t.
Definition: Core.h:90
Enables any type to be optional so it can exist in an uninitialized null state.
Definition: Optional.h:52
typename Super::template iterResult< Key > iterResult
Definition: MtMap.h:387
Key/value pair. A pair can be constructed with the syntax: (key() = value)
Definition: MtMap.h:50
List_ List
Rest of map.
Definition: MtMap.h:206
insertResult_seq< honey::priv::PairSeqGen< Pairs... >, Pairs... >::type insert(Pairs &&...pairs) const
Insert pairs of the form (key() = value) into the map.
Definition: MtMap.h:312
endResult_const end() const
Definition: MtMap.h:280
const Key key
Definition: MtMap.h:58
Common functions between map elem and the map tail specialization. Use through class MtMapElem...
Definition: MtMap.h:198
clearResult clear()
Clear map of all keys.
Definition: MtMap.h:340
MtMapElem(Map &&map)
Copy/Move any map type. Init with matching key in other map, recurse to tail.
Definition: MtMap.h:412
MtPair< Key, decltype(declval< Head >).get(Key()))> Pair
Definition: MtMap.h:124
const Pair & operator*() const
Definition: MtMap.h:136
MtMapIter< Subclass > beginResult
Result type of begin()
Definition: MtMap.h:267
eraseResult< Keys... > erase(Keys...) const
Erase keys from the map.
Definition: MtMap.h:335
typename Super::template eraseResult< Keys... > eraseResult
Definition: MtMap.h:392
Check if key exists at compile-time.
Definition: MtMap.h:259
bool hasKey(Key) const
Check if has key.
Definition: MtMap.h:261
Key_ Key
Key type.
Definition: MtMap.h:204
PrevIter operator--()
Definition: MtMap.h:131
void setDefaults(Map &&defaults)
Set any uninitialized optional values to the defaults provided. A default for a key must be a functor...
Definition: MtMap.h:435
bool operator!=(const Iter &rhs) const
Definition: MtMap.h:134
Check if empty at compile-time.
Definition: MtMap.h:348
Global Honeycomb namespace.
typename Super::template getResult< Key > getResult
Definition: MtMap.h:380
MtMapElem< mt::Void, mt::Void, mt::Void > MtMapTail
Tail of map list.
Definition: MtMap.h:32
friend class MtMapIter
Definition: MtMap.h:371
Subclass type
Definition: MtMap.h:223
typename priv::MtMap_< Pairs... >::type MtMap
Declare a map type with MtMap
Definition: MtMap.h:46
typename Super::template iterResult_const< Key > iterResult_const
Definition: MtMap.h:388
Val_ Val
Value type.
Definition: MtMap.h:205
OutSeq && map(Range &&, Seqs &&..., OutSeq &&, Func &&)
Transform a series of sequences into an output.