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