QxOrm  1.3.2
C++ Object Relational Mapping library
generic_container.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** http://www.qxorm.com/
00004 ** Copyright (C) 2013 Lionel Marty (contact@qxorm.com)
00005 **
00006 ** This file is part of the QxOrm library
00007 **
00008 ** This software is provided 'as-is', without any express or implied
00009 ** warranty. In no event will the authors be held liable for any
00010 ** damages arising from the use of this software
00011 **
00012 ** Commercial Usage
00013 ** Licensees holding valid commercial QxOrm licenses may use this file in
00014 ** accordance with the commercial license agreement provided with the
00015 ** Software or, alternatively, in accordance with the terms contained in
00016 ** a written agreement between you and Lionel Marty
00017 **
00018 ** GNU General Public License Usage
00019 ** Alternatively, this file may be used under the terms of the GNU
00020 ** General Public License version 3.0 as published by the Free Software
00021 ** Foundation and appearing in the file 'license.gpl3.txt' included in the
00022 ** packaging of this file. Please review the following information to
00023 ** ensure the GNU General Public License version 3.0 requirements will be
00024 ** met : http://www.gnu.org/copyleft/gpl.html
00025 **
00026 ** If you are unsure which license is appropriate for your use, or
00027 ** if you have questions regarding the use of this file, please contact :
00028 ** contact@qxorm.com
00029 **
00030 ****************************************************************************/
00031 
00032 #ifndef _QX_GENERIC_CONTAINER_H_
00033 #define _QX_GENERIC_CONTAINER_H_
00034 
00035 #ifdef _MSC_VER
00036 #pragma once
00037 #endif
00038 
00046 #include <boost/type_traits/is_pointer.hpp>
00047 
00048 #include <QxTraits/is_smart_ptr.h>
00049 #include <QxTraits/remove_attr.h>
00050 #include <QxTraits/remove_smart_ptr.h>
00051 #include <QxTraits/construct_ptr.h>
00052 
00053 namespace qx {
00054 namespace trait {
00055 
00056 class no_type
00057 { private: void dummy() const { ; } };
00058 
00063 template <class T>
00064 struct generic_container
00065 { 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; };
00066 
00067 template <typename Key, typename Value>
00068 struct generic_container_item
00069 {
00070 
00071    typedef Key type_key;
00072    typedef Value type_value;
00073    typedef typename qx::trait::remove_attr<Value>::type type_value_qx_tmp;
00074    typedef typename qx::trait::remove_smart_ptr<type_value_qx_tmp>::type type_value_qx;
00075 
00076    enum { is_key_pointer = (boost::is_pointer<type_key>::value || qx::trait::is_smart_ptr<type_key>::value) };
00077    enum { is_value_pointer = (boost::is_pointer<type_value>::value || qx::trait::is_smart_ptr<type_value>::value) };
00078 
00079 private:
00080 
00081    std::pair<type_key, type_value> m_pair;
00082 
00083 public:
00084 
00085    generic_container_item() { ; }
00086    generic_container_item(const Key & key, const Value & value) { m_pair = std::make_pair(key, value); }
00087    ~generic_container_item() { ; }
00088 
00089    inline type_key & key()                         { return m_pair.first; }
00090    inline type_value & value()                     { return m_pair.second; }
00091    inline const type_key & key() const             { return m_pair.first; }
00092    inline const type_value & value() const         { return m_pair.second; }
00093    inline type_value_qx & value_qx()               { return value_qx_Helper<is_value_pointer, type_value, type_value_qx, 0>::get(m_pair.second); }
00094    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); }
00095 
00096    inline void key(const Key & key)                { m_pair.first = key; }
00097    inline void value(const Value & value)          { m_pair.second = value; }
00098 
00099    static inline type_key newKey()     { return new_Helper<is_key_pointer, type_key, 0>::get(); }
00100    static inline type_value newValue() { return new_Helper<is_value_pointer, type_value, 0>::get(); }
00101 
00102 private:
00103 
00104    template <bool bIsPointer /* = true */, typename T, int dummy>
00105    struct new_Helper
00106    { static inline T get() { T t; qx::trait::construct_ptr<T>::get(t); return t; } };
00107 
00108    template <typename T, int dummy>
00109    struct new_Helper<false, T, dummy>
00110    { static inline T get() { return T(); } };
00111 
00112    template <bool bIsPointer /* = true */, typename T, typename U, int dummy>
00113    struct value_qx_Helper
00114    { static inline U & get(T & t) { return (* t); } };
00115 
00116    template <typename T, typename U, int dummy>
00117    struct value_qx_Helper<false, T, U, dummy>
00118    { static inline U & get(T & t) { return t; } };
00119 
00120 };
00121 
00122 } // namespace trait
00123 } // namespace qx
00124 
00125 #define QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(TypeContainer, TypeKey, TypeValue) \
00126 typedef qx::trait::generic_container_item< TypeKey, TypeValue > type_item; \
00127 typedef typename type_item::type_key type_key; \
00128 typedef typename type_item::type_value type_value; \
00129 typedef typename type_item::type_value_qx type_value_qx; \
00130 typedef typename TypeContainer::iterator type_iterator;
00131 
00132 namespace qx {
00133 namespace trait {
00134 namespace detail {
00135 
00136 template <typename Container, typename Item>
00137 struct generic_container_base
00138 {
00139 
00140    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, qx::trait::no_type, Item)
00141 
00142    static inline long size(const Container & t)                   { return static_cast<long>(t.size()); }
00143    static inline void clear(Container & t)                        { t.clear(); }
00144    static inline void reserve(Container & t, long l)              { t.reserve(l); }
00145    static inline type_item createItem()                           { return type_item(type_item::newKey(), type_item::newValue()); }
00146    static inline void insertItem(Container & t, type_item & item) { t.push_back(item.value()); }
00147    static inline type_iterator end(Container & t)                 { return t.end(); }
00148 
00149    static inline type_iterator begin(Container & t, type_item & item)
00150    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin()); return t.begin(); }
00151 
00152    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00153    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr); return itr; }
00154 
00155 };
00156 
00157 template <typename Container, typename Item>
00158 struct generic_container_base_without_reserve
00159 {
00160 
00161    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, qx::trait::no_type, Item)
00162 
00163    static inline long size(const Container & t)                   { return static_cast<long>(t.size()); }
00164    static inline void clear(Container & t)                        { t.clear(); }
00165    static inline void reserve(Container & t, long l)              { Q_UNUSED(t); Q_UNUSED(l); }
00166    static inline type_item createItem()                           { return type_item(type_item::newKey(), type_item::newValue()); }
00167    static inline void insertItem(Container & t, type_item & item) { t.push_back(item.value()); }
00168    static inline type_iterator end(Container & t)                 { return t.end(); }
00169 
00170    static inline type_iterator begin(Container & t, type_item & item)
00171    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin()); return t.begin(); }
00172 
00173    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00174    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr); return itr; }
00175 
00176 };
00177 
00178 template <typename Container, typename Item>
00179 struct generic_container_base_set
00180 {
00181 
00182    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, qx::trait::no_type, Item)
00183 
00184    static inline long size(const Container & t)                   { return static_cast<long>(t.size()); }
00185    static inline void clear(Container & t)                        { t.clear(); }
00186    static inline void reserve(Container & t, long l)              { Q_UNUSED(t); Q_UNUSED(l); }
00187    static inline type_item createItem()                           { return type_item(type_item::newKey(), type_item::newValue()); }
00188    static inline void insertItem(Container & t, type_item & item) { t.insert(item.value()); }
00189    static inline type_iterator end(Container & t)                 { return t.end(); }
00190 
00191    static inline type_iterator begin(Container & t, type_item & item)
00192    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin()); return t.begin(); }
00193 
00194    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00195    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr); return itr; }
00196 
00197 };
00198 
00199 template <typename Container, typename Key, typename Value>
00200 struct generic_container_base_key_value_std_style
00201 {
00202 
00203    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, Key, Value)
00204 
00205    static inline long size(const Container & t)                   { return static_cast<long>(t.size()); }
00206    static inline void clear(Container & t)                        { t.clear(); }
00207    static inline void reserve(Container & t, long l)              { t.reserve(l); }
00208    static inline type_item createItem()                           { return type_item(type_item::newKey(), type_item::newValue()); }
00209    static inline void insertItem(Container & t, type_item & item) { t.insert(std::make_pair(item.key(), item.value())); }
00210    static inline type_iterator end(Container & t)                 { return t.end(); }
00211 
00212    static inline type_iterator begin(Container & t, type_item & item)
00213    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin().second); item.key(* t.begin().first); return t.begin(); }
00214 
00215    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00216    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr.second); item.key(* itr.first); return itr; }
00217 
00218 };
00219 
00220 template <typename Container, typename Key, typename Value>
00221 struct generic_container_base_key_value_qt_style
00222 {
00223 
00224    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, Key, Value)
00225 
00226    static inline long size(const Container & t)                   { return static_cast<long>(t.size()); }
00227    static inline void clear(Container & t)                        { t.clear(); }
00228    static inline void reserve(Container & t, long l)              { t.reserve(l); }
00229    static inline type_item createItem()                           { return type_item(type_item::newKey(), type_item::newValue()); }
00230    static inline void insertItem(Container & t, type_item & item) { t.insert(item.key(), item.value()); }
00231    static inline type_iterator end(Container & t)                 { return t.end(); }
00232 
00233    static inline type_iterator begin(Container & t, type_item & item)
00234    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin().value()); item.key(* t.begin().key()); return t.begin(); }
00235 
00236    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00237    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr.value()); item.key(* itr.key()); return itr; }
00238 
00239 };
00240 
00241 } // namespace detail
00242 
00243 template <typename T>
00244 struct generic_container< std::vector<T> > : public qx::trait::detail::generic_container_base< std::vector<T>, T >
00245 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::vector, T), qx::trait::no_type, T) };
00246 
00247 template <typename T>
00248 struct generic_container< std::list<T> > : public qx::trait::detail::generic_container_base_without_reserve< std::list<T>, T >
00249 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::list, T), qx::trait::no_type, T) };
00250 
00251 template <typename T>
00252 struct generic_container< std::set<T> > : public qx::trait::detail::generic_container_base_set< std::set<T>, T >
00253 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::set, T), qx::trait::no_type, T) };
00254 
00255 template <typename Key, typename Value>
00256 struct generic_container< std::map<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_std_style< std::map<Key, Value>, Key, Value >
00257 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(std::map, Key, Value), Key, Value) };
00258 
00259 template <typename T>
00260 struct generic_container< boost::unordered_set<T> > : public qx::trait::detail::generic_container_base_set< boost::unordered_set<T>, T >
00261 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(boost::unordered_set, T), qx::trait::no_type, T) };
00262 
00263 template <typename T>
00264 struct generic_container< boost::unordered_multiset<T> > : public qx::trait::detail::generic_container_base_set< boost::unordered_multiset<T>, T >
00265 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(boost::unordered_multiset, T), qx::trait::no_type, T) };
00266 
00267 template <typename Key, typename Value>
00268 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 >
00269 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(boost::unordered_map, Key, Value), Key, Value) };
00270 
00271 template <typename Key, typename Value>
00272 struct generic_container< boost::unordered_multimap<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_std_style< boost::unordered_multimap<Key, Value>, Key, Value >
00273 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(boost::unordered_multimap, Key, Value), Key, Value) };
00274 
00275 #ifdef _QX_CPP_11_CONTAINER
00276 #ifndef BOOST_NO_CXX11_STD_UNORDERED
00277 
00278 template <typename T>
00279 struct generic_container< std::unordered_set<T> > : public qx::trait::detail::generic_container_base_set< std::unordered_set<T>, T >
00280 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::unordered_set, T), qx::trait::no_type, T) };
00281 
00282 template <typename T>
00283 struct generic_container< std::unordered_multiset<T> > : public qx::trait::detail::generic_container_base_set< std::unordered_multiset<T>, T >
00284 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::unordered_multiset, T), qx::trait::no_type, T) };
00285 
00286 template <typename Key, typename Value>
00287 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 >
00288 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(std::unordered_map, Key, Value), Key, Value) };
00289 
00290 template <typename Key, typename Value>
00291 struct generic_container< std::unordered_multimap<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_std_style< std::unordered_multimap<Key, Value>, Key, Value >
00292 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(std::unordered_multimap, Key, Value), Key, Value) };
00293 
00294 #endif // BOOST_NO_CXX11_STD_UNORDERED
00295 #endif // _QX_CPP_11_CONTAINER
00296 
00297 template <typename T>
00298 struct generic_container< QVector<T> > : public qx::trait::detail::generic_container_base< QVector<T>, T >
00299 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QVector, T), qx::trait::no_type, T) };
00300 
00301 template <typename T>
00302 struct generic_container< QList<T> > : public qx::trait::detail::generic_container_base_without_reserve< QList<T>, T >
00303 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QList, T), qx::trait::no_type, T) };
00304 
00305 template <typename T>
00306 struct generic_container< QLinkedList<T> > : public qx::trait::detail::generic_container_base_without_reserve< QLinkedList<T>, T >
00307 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QLinkedList, T), qx::trait::no_type, T) };
00308 
00309 template <typename T>
00310 struct generic_container< QSet<T> > : public qx::trait::detail::generic_container_base_set< QSet<T>, T >
00311 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QSet, T), qx::trait::no_type, T) };
00312 
00313 template <typename Key, typename Value>
00314 struct generic_container< QMap<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QMap<Key, Value>, Key, Value >
00315 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QMap, Key, Value), Key, Value) };
00316 
00317 template <typename Key, typename Value>
00318 struct generic_container< QMultiMap<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QMultiMap<Key, Value>, Key, Value >
00319 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QMultiMap, Key, Value), Key, Value) };
00320 
00321 template <typename Key, typename Value>
00322 struct generic_container< QHash<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QHash<Key, Value>, Key, Value >
00323 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QHash, Key, Value), Key, Value) };
00324 
00325 template <typename Key, typename Value>
00326 struct generic_container< QMultiHash<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QMultiHash<Key, Value>, Key, Value >
00327 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QMultiHash, Key, Value), Key, Value) };
00328 
00329 template <typename Key, typename Value>
00330 struct generic_container< qx::QxCollection<Key, Value> >
00331 {
00332 
00333    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(qx::QxCollection, Key, Value), Key, Value)
00334 
00335    static inline long size(const qx::QxCollection<Key, Value> & t)                     { return static_cast<long>(t.size()); }
00336    static inline void clear(qx::QxCollection<Key, Value> & t)                          { t.clear(); }
00337    static inline void reserve(qx::QxCollection<Key, Value> & t, long l)                { t.reserve(l); }
00338    static inline type_item createItem()                                                { return type_item(type_item::newKey(), type_item::newValue()); }
00339    static inline void insertItem(qx::QxCollection<Key, Value> & t, type_item & item)   { t.insert(item.key(), item.value()); }
00340    static inline type_iterator end(qx::QxCollection<Key, Value> & t)                   { return t.end(); }
00341 
00342    static inline type_iterator begin(qx::QxCollection<Key, Value> & t, type_item & item)
00343    { if (t.size() <= 0) { return t.end(); }; item.value(t.getByIndex(0)); item.key(t.getKeyByIndex(0)); return t.begin(); }
00344 
00345    static inline type_iterator next(qx::QxCollection<Key, Value> & t, type_iterator itr, type_item & item)
00346    { 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; }
00347 
00348 };
00349 
00350 } // namespace trait
00351 } // namespace qx
00352 
00353 #endif // _QX_GENERIC_CONTAINER_H_