generic_container.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422
  1. /****************************************************************************
  2. **
  3. ** https://www.qxorm.com/
  4. ** Copyright (C) 2013 Lionel Marty (contact@qxorm.com)
  5. **
  6. ** This file is part of the QxOrm library
  7. **
  8. ** This software is provided 'as-is', without any express or implied
  9. ** warranty. In no event will the authors be held liable for any
  10. ** damages arising from the use of this software
  11. **
  12. ** Commercial Usage
  13. ** Licensees holding valid commercial QxOrm licenses may use this file in
  14. ** accordance with the commercial license agreement provided with the
  15. ** Software or, alternatively, in accordance with the terms contained in
  16. ** a written agreement between you and Lionel Marty
  17. **
  18. ** GNU General Public License Usage
  19. ** Alternatively, this file may be used under the terms of the GNU
  20. ** General Public License version 3.0 as published by the Free Software
  21. ** Foundation and appearing in the file 'license.gpl3.txt' included in the
  22. ** packaging of this file. Please review the following information to
  23. ** ensure the GNU General Public License version 3.0 requirements will be
  24. ** met : http://www.gnu.org/copyleft/gpl.html
  25. **
  26. ** If you are unsure which license is appropriate for your use, or
  27. ** if you have questions regarding the use of this file, please contact :
  28. ** contact@qxorm.com
  29. **
  30. ****************************************************************************/
  31. #ifndef _QX_GENERIC_CONTAINER_H_
  32. #define _QX_GENERIC_CONTAINER_H_
  33. #ifdef _MSC_VER
  34. #pragma once
  35. #endif
  36. /*!
  37. * \file generic_container.h
  38. * \author Lionel Marty
  39. * \ingroup QxTraits
  40. * \brief qx::trait::generic_container<T> : provide some tools to manage all containers without knowing its type
  41. */
  42. #include <QxTraits/is_smart_ptr.h>
  43. #include <QxTraits/remove_attr.h>
  44. #include <QxTraits/remove_smart_ptr.h>
  45. #include <QxTraits/construct_ptr.h>
  46. namespace qx {
  47. namespace trait {
  48. class no_type
  49. { private: void dummy() const { ; } };
  50. /*!
  51. * \ingroup QxTraits
  52. * \brief qx::trait::generic_container<T> : provide some tools to manage all containers without knowing its type
  53. */
  54. template <class T>
  55. struct generic_container
  56. { typedef no_type type_item; typedef no_type type_key; typedef no_type type_value; typedef no_type type_value_qx; typedef no_type type_iterator; };
  57. template <typename Key, typename Value>
  58. struct generic_container_item
  59. {
  60. typedef Key type_key;
  61. typedef Value type_value;
  62. typedef typename qx::trait::remove_attr<Value>::type type_value_qx_tmp;
  63. typedef typename qx::trait::remove_smart_ptr<type_value_qx_tmp>::type type_value_qx;
  64. enum { is_key_pointer = (std::is_pointer<type_key>::value || qx::trait::is_smart_ptr<type_key>::value) };
  65. enum { is_value_pointer = (std::is_pointer<type_value>::value || qx::trait::is_smart_ptr<type_value>::value) };
  66. private:
  67. std::pair<type_key, type_value> m_pair;
  68. public:
  69. generic_container_item() { ; }
  70. generic_container_item(const Key & key, const Value & value) { m_pair = std::make_pair(key, value); }
  71. ~generic_container_item() { ; }
  72. inline type_key & key() { return m_pair.first; }
  73. inline type_value & value() { return m_pair.second; }
  74. inline const type_key & key() const { return m_pair.first; }
  75. inline const type_value & value() const { return m_pair.second; }
  76. inline type_value_qx & value_qx() { return value_qx_Helper<is_value_pointer, type_value, type_value_qx, 0>::get(m_pair.second); }
  77. inline const type_value_qx & value_qx() const { return value_qx_Helper<is_value_pointer, type_value, type_value_qx, 0>::get(m_pair.second); }
  78. inline void key(const Key & key) { m_pair.first = key; }
  79. inline void value(const Value & value) { m_pair.second = value; }
  80. static inline type_key newKey() { return new_Helper<is_key_pointer, type_key, 0>::get(); }
  81. static inline type_value newValue() { return new_Helper<is_value_pointer, type_value, 0>::get(); }
  82. private:
  83. template <bool bIsPointer /* = true */, typename T, int dummy>
  84. struct new_Helper
  85. { static inline T get() { T t; qx::trait::construct_ptr<T>::get(t); return t; } };
  86. template <typename T, int dummy>
  87. struct new_Helper<false, T, dummy>
  88. { static inline T get() { return T(); } };
  89. template <bool bIsPointer /* = true */, typename T, typename U, int dummy>
  90. struct value_qx_Helper
  91. { static inline U & get(T & t) { return (* t); } };
  92. template <typename T, typename U, int dummy>
  93. struct value_qx_Helper<false, T, U, dummy>
  94. { static inline U & get(T & t) { return t; } };
  95. };
  96. } // namespace trait
  97. } // namespace qx
  98. #define QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(TypeContainer, TypeKey, TypeValue) \
  99. typedef qx::trait::generic_container_item< TypeKey, TypeValue > type_item; \
  100. typedef typename type_item::type_key type_key; \
  101. typedef typename type_item::type_value type_value; \
  102. typedef typename type_item::type_value_qx type_value_qx; \
  103. typedef typename TypeContainer::iterator type_iterator;
  104. namespace qx {
  105. namespace trait {
  106. namespace detail {
  107. template <typename Container, typename Item>
  108. struct generic_container_base
  109. {
  110. QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, qx::trait::no_type, Item)
  111. static inline long size(const Container & t) { return static_cast<long>(t.size()); }
  112. static inline void clear(Container & t) { t.clear(); }
  113. static inline void reserve(Container & t, long l) { t.reserve(l); }
  114. static inline type_item createItem() { return type_item(type_item::newKey(), type_item::newValue()); }
  115. static inline Item * insertItem(Container & t, type_item & item) { t.push_back(item.value()); return (& t.back()); }
  116. static inline type_iterator end(Container & t) { return t.end(); }
  117. static inline type_iterator begin(Container & t, type_item & item)
  118. { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin()); return t.begin(); }
  119. static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
  120. { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr); return itr; }
  121. };
  122. template <typename Container, typename Item>
  123. struct generic_container_base_without_reserve
  124. {
  125. QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, qx::trait::no_type, Item)
  126. static inline long size(const Container & t) { return static_cast<long>(t.size()); }
  127. static inline void clear(Container & t) { t.clear(); }
  128. static inline void reserve(Container & t, long l) { Q_UNUSED(t); Q_UNUSED(l); }
  129. static inline type_item createItem() { return type_item(type_item::newKey(), type_item::newValue()); }
  130. static inline Item * insertItem(Container & t, type_item & item) { t.push_back(item.value()); return (& t.back()); }
  131. static inline type_iterator end(Container & t) { return t.end(); }
  132. static inline type_iterator begin(Container & t, type_item & item)
  133. { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin()); return t.begin(); }
  134. static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
  135. { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr); return itr; }
  136. };
  137. template <typename Container, typename Item>
  138. struct generic_container_base_set
  139. {
  140. QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, qx::trait::no_type, Item)
  141. static inline long size(const Container & t) { return static_cast<long>(t.size()); }
  142. static inline void clear(Container & t) { t.clear(); }
  143. static inline void reserve(Container & t, long l) { Q_UNUSED(t); Q_UNUSED(l); }
  144. static inline type_item createItem() { return type_item(type_item::newKey(), type_item::newValue()); }
  145. static inline Item * insertItem(Container & t, type_item & item) { return const_cast<Item *>(& (* (t.insert(item.value()).first))); }
  146. static inline type_iterator end(Container & t) { return t.end(); }
  147. static inline type_iterator begin(Container & t, type_item & item)
  148. { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin()); return t.begin(); }
  149. static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
  150. { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr); return itr; }
  151. };
  152. template <typename Container, typename Item>
  153. struct generic_container_base_multi_set
  154. {
  155. QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, qx::trait::no_type, Item)
  156. static inline long size(const Container & t) { return static_cast<long>(t.size()); }
  157. static inline void clear(Container & t) { t.clear(); }
  158. static inline void reserve(Container & t, long l) { Q_UNUSED(t); Q_UNUSED(l); }
  159. static inline type_item createItem() { return type_item(type_item::newKey(), type_item::newValue()); }
  160. static inline Item * insertItem(Container & t, type_item & item) { return const_cast<Item *>(& (* (t.insert(item.value())))); }
  161. static inline type_iterator end(Container & t) { return t.end(); }
  162. static inline type_iterator begin(Container & t, type_item & item)
  163. { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin()); return t.begin(); }
  164. static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
  165. { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr); return itr; }
  166. };
  167. template <typename Container, typename Key, typename Value>
  168. struct generic_container_base_key_value_std_style
  169. {
  170. QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, Key, Value)
  171. static inline long size(const Container & t) { return static_cast<long>(t.size()); }
  172. static inline void clear(Container & t) { t.clear(); }
  173. static inline void reserve(Container & t, long l) { t.reserve(l); }
  174. static inline type_item createItem() { return type_item(type_item::newKey(), type_item::newValue()); }
  175. static inline Value * insertItem(Container & t, type_item & item) { return (& (t.insert(std::make_pair(item.key(), item.value())).first->second)); }
  176. static inline type_iterator end(Container & t) { return t.end(); }
  177. static inline type_iterator begin(Container & t, type_item & item)
  178. { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin().second); item.key(* t.begin().first); return t.begin(); }
  179. static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
  180. { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr.second); item.key(* itr.first); return itr; }
  181. };
  182. template <typename Container, typename Key, typename Value>
  183. struct generic_container_base_key_value_without_reserve
  184. {
  185. QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, Key, Value)
  186. static inline long size(const Container & t) { return static_cast<long>(t.size()); }
  187. static inline void clear(Container & t) { t.clear(); }
  188. static inline void reserve(Container & t, long l) { Q_UNUSED(t); Q_UNUSED(l); }
  189. static inline type_item createItem() { return type_item(type_item::newKey(), type_item::newValue()); }
  190. static inline Value * insertItem(Container & t, type_item & item) { return (& (t.insert(std::make_pair(item.key(), item.value())).first->second)); }
  191. static inline type_iterator end(Container & t) { return t.end(); }
  192. static inline type_iterator begin(Container & t, type_item & item)
  193. { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin().second); item.key(* t.begin().first); return t.begin(); }
  194. static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
  195. { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr.second); item.key(* itr.first); return itr; }
  196. };
  197. template <typename Container, typename Key, typename Value>
  198. struct generic_container_base_key_value_multi_std_style
  199. {
  200. QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, Key, Value)
  201. static inline long size(const Container & t) { return static_cast<long>(t.size()); }
  202. static inline void clear(Container & t) { t.clear(); }
  203. static inline void reserve(Container & t, long l) { t.reserve(l); }
  204. static inline type_item createItem() { return type_item(type_item::newKey(), type_item::newValue()); }
  205. static inline Value * insertItem(Container & t, type_item & item) { return (& (t.insert(std::make_pair(item.key(), item.value()))->second)); }
  206. static inline type_iterator end(Container & t) { return t.end(); }
  207. static inline type_iterator begin(Container & t, type_item & item)
  208. { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin().second); item.key(* t.begin().first); return t.begin(); }
  209. static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
  210. { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr.second); item.key(* itr.first); return itr; }
  211. };
  212. template <typename Container, typename Key, typename Value>
  213. struct generic_container_base_key_value_qt_style
  214. {
  215. QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, Key, Value)
  216. static inline long size(const Container & t) { return static_cast<long>(t.size()); }
  217. static inline void clear(Container & t) { t.clear(); }
  218. static inline void reserve(Container & t, long l) { t.reserve(l); }
  219. static inline type_item createItem() { return type_item(type_item::newKey(), type_item::newValue()); }
  220. static inline Value * insertItem(Container & t, type_item & item) { return (& (t.insert(item.key(), item.value()).value())); }
  221. static inline type_iterator end(Container & t) { return t.end(); }
  222. static inline type_iterator begin(Container & t, type_item & item)
  223. { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin().value()); item.key(* t.begin().key()); return t.begin(); }
  224. static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
  225. { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr.value()); item.key(* itr.key()); return itr; }
  226. };
  227. } // namespace detail
  228. template <typename T>
  229. struct generic_container< std::vector<T> > : public qx::trait::detail::generic_container_base< std::vector<T>, T >
  230. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::vector, T), qx::trait::no_type, T) };
  231. template <typename T>
  232. struct generic_container< std::list<T> > : public qx::trait::detail::generic_container_base_without_reserve< std::list<T>, T >
  233. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::list, T), qx::trait::no_type, T) };
  234. template <typename T>
  235. struct generic_container< std::set<T> > : public qx::trait::detail::generic_container_base_set< std::set<T>, T >
  236. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::set, T), qx::trait::no_type, T) };
  237. template <typename Key, typename Value>
  238. struct generic_container< std::map<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_without_reserve< std::map<Key, Value>, Key, Value >
  239. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(std::map, Key, Value), Key, Value) };
  240. #ifdef _QX_ENABLE_BOOST
  241. template <typename T>
  242. struct generic_container< boost::unordered_set<T> > : public qx::trait::detail::generic_container_base_set< boost::unordered_set<T>, T >
  243. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(boost::unordered_set, T), qx::trait::no_type, T) };
  244. template <typename T>
  245. struct generic_container< boost::unordered_multiset<T> > : public qx::trait::detail::generic_container_base_multi_set< boost::unordered_multiset<T>, T >
  246. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(boost::unordered_multiset, T), qx::trait::no_type, T) };
  247. template <typename Key, typename Value>
  248. struct generic_container< boost::unordered_map<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_std_style< boost::unordered_map<Key, Value>, Key, Value >
  249. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(boost::unordered_map, Key, Value), Key, Value) };
  250. template <typename Key, typename Value>
  251. struct generic_container< boost::unordered_multimap<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_multi_std_style< boost::unordered_multimap<Key, Value>, Key, Value >
  252. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(boost::unordered_multimap, Key, Value), Key, Value) };
  253. #endif // _QX_ENABLE_BOOST
  254. template <typename T>
  255. struct generic_container< std::unordered_set<T> > : public qx::trait::detail::generic_container_base_set< std::unordered_set<T>, T >
  256. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::unordered_set, T), qx::trait::no_type, T) };
  257. template <typename T>
  258. struct generic_container< std::unordered_multiset<T> > : public qx::trait::detail::generic_container_base_multi_set< std::unordered_multiset<T>, T >
  259. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::unordered_multiset, T), qx::trait::no_type, T) };
  260. template <typename Key, typename Value>
  261. struct generic_container< std::unordered_map<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_std_style< std::unordered_map<Key, Value>, Key, Value >
  262. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(std::unordered_map, Key, Value), Key, Value) };
  263. template <typename Key, typename Value>
  264. struct generic_container< std::unordered_multimap<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_multi_std_style< std::unordered_multimap<Key, Value>, Key, Value >
  265. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(std::unordered_multimap, Key, Value), Key, Value) };
  266. template <typename T>
  267. struct generic_container< QVector<T> > : public qx::trait::detail::generic_container_base< QVector<T>, T >
  268. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QVector, T), qx::trait::no_type, T) };
  269. #if (QT_VERSION >= 0x040700)
  270. template <typename T>
  271. struct generic_container< QList<T> > : public qx::trait::detail::generic_container_base< QList<T>, T >
  272. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QList, T), qx::trait::no_type, T) };
  273. #else // (QT_VERSION >= 0x040700)
  274. template <typename T>
  275. struct generic_container< QList<T> > : public qx::trait::detail::generic_container_base_without_reserve< QList<T>, T >
  276. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QList, T), qx::trait::no_type, T) };
  277. #endif // (QT_VERSION >= 0x040700)
  278. template <typename T>
  279. struct generic_container< QLinkedList<T> > : public qx::trait::detail::generic_container_base_without_reserve< QLinkedList<T>, T >
  280. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QLinkedList, T), qx::trait::no_type, T) };
  281. template <typename T>
  282. struct generic_container< QSet<T> > : public qx::trait::detail::generic_container_base_multi_set< QSet<T>, T >
  283. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QSet, T), qx::trait::no_type, T) };
  284. template <typename Key, typename Value>
  285. struct generic_container< QMap<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QMap<Key, Value>, Key, Value >
  286. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QMap, Key, Value), Key, Value) };
  287. template <typename Key, typename Value>
  288. struct generic_container< QMultiMap<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QMultiMap<Key, Value>, Key, Value >
  289. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QMultiMap, Key, Value), Key, Value) };
  290. template <typename Key, typename Value>
  291. struct generic_container< QHash<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QHash<Key, Value>, Key, Value >
  292. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QHash, Key, Value), Key, Value) };
  293. template <typename Key, typename Value>
  294. struct generic_container< QMultiHash<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QMultiHash<Key, Value>, Key, Value >
  295. { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QMultiHash, Key, Value), Key, Value) };
  296. template <typename Key, typename Value>
  297. struct generic_container< qx::QxCollection<Key, Value> >
  298. {
  299. QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(qx::QxCollection, Key, Value), Key, Value)
  300. static inline long size(const qx::QxCollection<Key, Value> & t) { return static_cast<long>(t.size()); }
  301. static inline void clear(qx::QxCollection<Key, Value> & t) { t.clear(); }
  302. static inline void reserve(qx::QxCollection<Key, Value> & t, long l) { t.reserve(l); }
  303. static inline type_item createItem() { return type_item(type_item::newKey(), type_item::newValue()); }
  304. static inline Value * insertItem(qx::QxCollection<Key, Value> & t, type_item & item) { t.insert(item.key(), item.value()); return const_cast<Value *>(& t.getByKey(item.key())); }
  305. static inline type_iterator end(qx::QxCollection<Key, Value> & t) { return t.end(); }
  306. static inline type_iterator begin(qx::QxCollection<Key, Value> & t, type_item & item)
  307. { if (t.size() <= 0) { return t.end(); }; item.value(t.getByIndex(0)); item.key(t.getKeyByIndex(0)); return t.begin(); }
  308. static inline type_iterator next(qx::QxCollection<Key, Value> & t, type_iterator itr, type_item & item)
  309. { itr++; if (itr == t.end()) { return t.end(); }; long l = (itr - t.begin()); item.value(t.getByIndex(l)); item.key(t.getKeyByIndex(l)); return itr; }
  310. };
  311. } // namespace trait
  312. } // namespace qx
  313. #endif // _QX_GENERIC_CONTAINER_H_