QxOrm  1.4.7
C++ Object Relational Mapping library
generic_container.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 **
00003 ** https://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 <QxTraits/is_smart_ptr.h>
00047 #include <QxTraits/remove_attr.h>
00048 #include <QxTraits/remove_smart_ptr.h>
00049 #include <QxTraits/construct_ptr.h>
00050 
00051 namespace qx {
00052 namespace trait {
00053 
00054 class no_type
00055 { private: void dummy() const { ; } };
00056 
00061 template <class T>
00062 struct generic_container
00063 { 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; };
00064 
00065 template <typename Key, typename Value>
00066 struct generic_container_item
00067 {
00068 
00069    typedef Key type_key;
00070    typedef Value type_value;
00071    typedef typename qx::trait::remove_attr<Value>::type type_value_qx_tmp;
00072    typedef typename qx::trait::remove_smart_ptr<type_value_qx_tmp>::type type_value_qx;
00073 
00074    enum { is_key_pointer = (std::is_pointer<type_key>::value || qx::trait::is_smart_ptr<type_key>::value) };
00075    enum { is_value_pointer = (std::is_pointer<type_value>::value || qx::trait::is_smart_ptr<type_value>::value) };
00076 
00077 private:
00078 
00079    std::pair<type_key, type_value> m_pair;
00080 
00081 public:
00082 
00083    generic_container_item() { ; }
00084    generic_container_item(const Key & key, const Value & value) { m_pair = std::make_pair(key, value); }
00085    ~generic_container_item() { ; }
00086 
00087    inline type_key & key()                         { return m_pair.first; }
00088    inline type_value & value()                     { return m_pair.second; }
00089    inline const type_key & key() const             { return m_pair.first; }
00090    inline const type_value & value() const         { return m_pair.second; }
00091    inline type_value_qx & value_qx()               { return value_qx_Helper<is_value_pointer, type_value, type_value_qx, 0>::get(m_pair.second); }
00092    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); }
00093 
00094    inline void key(const Key & key)                { m_pair.first = key; }
00095    inline void value(const Value & value)          { m_pair.second = value; }
00096 
00097    static inline type_key newKey()     { return new_Helper<is_key_pointer, type_key, 0>::get(); }
00098    static inline type_value newValue() { return new_Helper<is_value_pointer, type_value, 0>::get(); }
00099 
00100 private:
00101 
00102    template <bool bIsPointer /* = true */, typename T, int dummy>
00103    struct new_Helper
00104    { static inline T get() { T t; qx::trait::construct_ptr<T>::get(t); return t; } };
00105 
00106    template <typename T, int dummy>
00107    struct new_Helper<false, T, dummy>
00108    { static inline T get() { return T(); } };
00109 
00110    template <bool bIsPointer /* = true */, typename T, typename U, int dummy>
00111    struct value_qx_Helper
00112    { static inline U & get(T & t) { return (* t); } };
00113 
00114    template <typename T, typename U, int dummy>
00115    struct value_qx_Helper<false, T, U, dummy>
00116    { static inline U & get(T & t) { return t; } };
00117 
00118 };
00119 
00120 } // namespace trait
00121 } // namespace qx
00122 
00123 #define QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(TypeContainer, TypeKey, TypeValue) \
00124 typedef qx::trait::generic_container_item< TypeKey, TypeValue > type_item; \
00125 typedef typename type_item::type_key type_key; \
00126 typedef typename type_item::type_value type_value; \
00127 typedef typename type_item::type_value_qx type_value_qx; \
00128 typedef typename TypeContainer::iterator type_iterator;
00129 
00130 namespace qx {
00131 namespace trait {
00132 namespace detail {
00133 
00134 template <typename Container, typename Item>
00135 struct generic_container_base
00136 {
00137 
00138    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, qx::trait::no_type, Item)
00139 
00140    static inline long size(const Container & t)                      { return static_cast<long>(t.size()); }
00141    static inline void clear(Container & t)                           { t.clear(); }
00142    static inline void reserve(Container & t, long l)                 { t.reserve(l); }
00143    static inline type_item createItem()                              { return type_item(type_item::newKey(), type_item::newValue()); }
00144    static inline Item * insertItem(Container & t, type_item & item)  { t.push_back(item.value()); return (& t.back()); }
00145    static inline type_iterator end(Container & t)                    { return t.end(); }
00146 
00147    static inline type_iterator begin(Container & t, type_item & item)
00148    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin()); return t.begin(); }
00149 
00150    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00151    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr); return itr; }
00152 
00153 };
00154 
00155 template <typename Container, typename Item>
00156 struct generic_container_base_without_reserve
00157 {
00158 
00159    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, qx::trait::no_type, Item)
00160 
00161    static inline long size(const Container & t)                      { return static_cast<long>(t.size()); }
00162    static inline void clear(Container & t)                           { t.clear(); }
00163    static inline void reserve(Container & t, long l)                 { Q_UNUSED(t); Q_UNUSED(l); }
00164    static inline type_item createItem()                              { return type_item(type_item::newKey(), type_item::newValue()); }
00165    static inline Item * insertItem(Container & t, type_item & item)  { t.push_back(item.value()); return (& t.back()); }
00166    static inline type_iterator end(Container & t)                    { return t.end(); }
00167 
00168    static inline type_iterator begin(Container & t, type_item & item)
00169    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin()); return t.begin(); }
00170 
00171    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00172    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr); return itr; }
00173 
00174 };
00175 
00176 template <typename Container, typename Item>
00177 struct generic_container_base_set
00178 {
00179 
00180    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, qx::trait::no_type, Item)
00181 
00182    static inline long size(const Container & t)                      { return static_cast<long>(t.size()); }
00183    static inline void clear(Container & t)                           { t.clear(); }
00184    static inline void reserve(Container & t, long l)                 { Q_UNUSED(t); Q_UNUSED(l); }
00185    static inline type_item createItem()                              { return type_item(type_item::newKey(), type_item::newValue()); }
00186    static inline Item * insertItem(Container & t, type_item & item)  { return const_cast<Item *>(& (* (t.insert(item.value()).first))); }
00187    static inline type_iterator end(Container & t)                    { return t.end(); }
00188 
00189    static inline type_iterator begin(Container & t, type_item & item)
00190    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin()); return t.begin(); }
00191 
00192    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00193    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr); return itr; }
00194 
00195 };
00196 
00197 template <typename Container, typename Item>
00198 struct generic_container_base_multi_set
00199 {
00200 
00201    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, qx::trait::no_type, Item)
00202 
00203    static inline long size(const Container & t)                      { return static_cast<long>(t.size()); }
00204    static inline void clear(Container & t)                           { t.clear(); }
00205    static inline void reserve(Container & t, long l)                 { Q_UNUSED(t); Q_UNUSED(l); }
00206    static inline type_item createItem()                              { return type_item(type_item::newKey(), type_item::newValue()); }
00207    static inline Item * insertItem(Container & t, type_item & item)  { return const_cast<Item *>(& (* (t.insert(item.value())))); }
00208    static inline type_iterator end(Container & t)                    { return t.end(); }
00209 
00210    static inline type_iterator begin(Container & t, type_item & item)
00211    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin()); return t.begin(); }
00212 
00213    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00214    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr); return itr; }
00215 
00216 };
00217 
00218 template <typename Container, typename Key, typename Value>
00219 struct generic_container_base_key_value_std_style
00220 {
00221 
00222    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, Key, Value)
00223 
00224    static inline long size(const Container & t)                      { return static_cast<long>(t.size()); }
00225    static inline void clear(Container & t)                           { t.clear(); }
00226    static inline void reserve(Container & t, long l)                 { t.reserve(l); }
00227    static inline type_item createItem()                              { return type_item(type_item::newKey(), type_item::newValue()); }
00228    static inline Value * insertItem(Container & t, type_item & item) { return (& (t.insert(std::make_pair(item.key(), item.value())).first->second)); }
00229    static inline type_iterator end(Container & t)                    { return t.end(); }
00230 
00231    static inline type_iterator begin(Container & t, type_item & item)
00232    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin().second); item.key(* t.begin().first); return t.begin(); }
00233 
00234    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00235    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr.second); item.key(* itr.first); return itr; }
00236 
00237 };
00238 
00239 template <typename Container, typename Key, typename Value>
00240 struct generic_container_base_key_value_without_reserve
00241 {
00242 
00243    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, Key, Value)
00244 
00245    static inline long size(const Container & t)                      { return static_cast<long>(t.size()); }
00246    static inline void clear(Container & t)                           { t.clear(); }
00247    static inline void reserve(Container & t, long l)                 { Q_UNUSED(t); Q_UNUSED(l); }
00248    static inline type_item createItem()                              { return type_item(type_item::newKey(), type_item::newValue()); }
00249    static inline Value * insertItem(Container & t, type_item & item) { return (& (t.insert(std::make_pair(item.key(), item.value())).first->second)); }
00250    static inline type_iterator end(Container & t)                    { return t.end(); }
00251 
00252    static inline type_iterator begin(Container & t, type_item & item)
00253    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin().second); item.key(* t.begin().first); return t.begin(); }
00254 
00255    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00256    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr.second); item.key(* itr.first); return itr; }
00257 
00258 };
00259 
00260 template <typename Container, typename Key, typename Value>
00261 struct generic_container_base_key_value_multi_std_style
00262 {
00263 
00264    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, Key, Value)
00265 
00266    static inline long size(const Container & t)                      { return static_cast<long>(t.size()); }
00267    static inline void clear(Container & t)                           { t.clear(); }
00268    static inline void reserve(Container & t, long l)                 { t.reserve(l); }
00269    static inline type_item createItem()                              { return type_item(type_item::newKey(), type_item::newValue()); }
00270    static inline Value * insertItem(Container & t, type_item & item) { return (& (t.insert(std::make_pair(item.key(), item.value()))->second)); }
00271    static inline type_iterator end(Container & t)                    { return t.end(); }
00272 
00273    static inline type_iterator begin(Container & t, type_item & item)
00274    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin().second); item.key(* t.begin().first); return t.begin(); }
00275 
00276    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00277    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr.second); item.key(* itr.first); return itr; }
00278 
00279 };
00280 
00281 template <typename Container, typename Key, typename Value>
00282 struct generic_container_base_key_value_qt_style
00283 {
00284 
00285    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(Container, Key, Value)
00286 
00287    static inline long size(const Container & t)                      { return static_cast<long>(t.size()); }
00288    static inline void clear(Container & t)                           { t.clear(); }
00289    static inline void reserve(Container & t, long l)                 { t.reserve(l); }
00290    static inline type_item createItem()                              { return type_item(type_item::newKey(), type_item::newValue()); }
00291    static inline Value * insertItem(Container & t, type_item & item) { return (& (t.insert(item.key(), item.value()).value())); }
00292    static inline type_iterator end(Container & t)                    { return t.end(); }
00293 
00294    static inline type_iterator begin(Container & t, type_item & item)
00295    { if (t.size() <= 0) { return t.end(); }; item.value(* t.begin().value()); item.key(* t.begin().key()); return t.begin(); }
00296 
00297    static inline type_iterator next(Container & t, type_iterator itr, type_item & item)
00298    { itr++; if (itr == t.end()) { return t.end(); }; item.value(* itr.value()); item.key(* itr.key()); return itr; }
00299 
00300 };
00301 
00302 } // namespace detail
00303 
00304 template <typename T>
00305 struct generic_container< std::vector<T> > : public qx::trait::detail::generic_container_base< std::vector<T>, T >
00306 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::vector, T), qx::trait::no_type, T) };
00307 
00308 template <typename T>
00309 struct generic_container< std::list<T> > : public qx::trait::detail::generic_container_base_without_reserve< std::list<T>, T >
00310 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::list, T), qx::trait::no_type, T) };
00311 
00312 template <typename T>
00313 struct generic_container< std::set<T> > : public qx::trait::detail::generic_container_base_set< std::set<T>, T >
00314 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::set, T), qx::trait::no_type, T) };
00315 
00316 template <typename Key, typename Value>
00317 struct generic_container< std::map<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_without_reserve< std::map<Key, Value>, Key, Value >
00318 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(std::map, Key, Value), Key, Value) };
00319 
00320 #ifdef _QX_ENABLE_BOOST
00321 
00322 template <typename T>
00323 struct generic_container< boost::unordered_set<T> > : public qx::trait::detail::generic_container_base_set< boost::unordered_set<T>, T >
00324 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(boost::unordered_set, T), qx::trait::no_type, T) };
00325 
00326 template <typename T>
00327 struct generic_container< boost::unordered_multiset<T> > : public qx::trait::detail::generic_container_base_multi_set< boost::unordered_multiset<T>, T >
00328 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(boost::unordered_multiset, T), qx::trait::no_type, T) };
00329 
00330 template <typename Key, typename Value>
00331 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 >
00332 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(boost::unordered_map, Key, Value), Key, Value) };
00333 
00334 template <typename Key, typename Value>
00335 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 >
00336 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(boost::unordered_multimap, Key, Value), Key, Value) };
00337 
00338 #endif // _QX_ENABLE_BOOST
00339 
00340 template <typename T>
00341 struct generic_container< std::unordered_set<T> > : public qx::trait::detail::generic_container_base_set< std::unordered_set<T>, T >
00342 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::unordered_set, T), qx::trait::no_type, T) };
00343 
00344 template <typename T>
00345 struct generic_container< std::unordered_multiset<T> > : public qx::trait::detail::generic_container_base_multi_set< std::unordered_multiset<T>, T >
00346 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(std::unordered_multiset, T), qx::trait::no_type, T) };
00347 
00348 template <typename Key, typename Value>
00349 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 >
00350 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(std::unordered_map, Key, Value), Key, Value) };
00351 
00352 template <typename Key, typename Value>
00353 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 >
00354 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(std::unordered_multimap, Key, Value), Key, Value) };
00355 
00356 template <typename T>
00357 struct generic_container< QVector<T> > : public qx::trait::detail::generic_container_base< QVector<T>, T >
00358 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QVector, T), qx::trait::no_type, T) };
00359 
00360 #if (QT_VERSION >= 0x040700)
00361 
00362 template <typename T>
00363 struct generic_container< QList<T> > : public qx::trait::detail::generic_container_base< QList<T>, T >
00364 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QList, T), qx::trait::no_type, T) };
00365 
00366 #else // (QT_VERSION >= 0x040700)
00367 
00368 template <typename T>
00369 struct generic_container< QList<T> > : public qx::trait::detail::generic_container_base_without_reserve< QList<T>, T >
00370 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QList, T), qx::trait::no_type, T) };
00371 
00372 #endif // (QT_VERSION >= 0x040700)
00373 
00374 template <typename T>
00375 struct generic_container< QLinkedList<T> > : public qx::trait::detail::generic_container_base_without_reserve< QLinkedList<T>, T >
00376 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QLinkedList, T), qx::trait::no_type, T) };
00377 
00378 template <typename T>
00379 struct generic_container< QSet<T> > : public qx::trait::detail::generic_container_base_multi_set< QSet<T>, T >
00380 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1(QSet, T), qx::trait::no_type, T) };
00381 
00382 template <typename Key, typename Value>
00383 struct generic_container< QMap<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QMap<Key, Value>, Key, Value >
00384 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QMap, Key, Value), Key, Value) };
00385 
00386 template <typename Key, typename Value>
00387 struct generic_container< QMultiMap<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QMultiMap<Key, Value>, Key, Value >
00388 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QMultiMap, Key, Value), Key, Value) };
00389 
00390 template <typename Key, typename Value>
00391 struct generic_container< QHash<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QHash<Key, Value>, Key, Value >
00392 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QHash, Key, Value), Key, Value) };
00393 
00394 template <typename Key, typename Value>
00395 struct generic_container< QMultiHash<Key, Value> > : public qx::trait::detail::generic_container_base_key_value_qt_style< QMultiHash<Key, Value>, Key, Value >
00396 { QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(QMultiHash, Key, Value), Key, Value) };
00397 
00398 template <typename Key, typename Value>
00399 struct generic_container< qx::QxCollection<Key, Value> >
00400 {
00401 
00402    QX_TRAIT_GENERIC_CONTAINER_TYPEDEF(QX_TEMPLATE_T_P1_P2(qx::QxCollection, Key, Value), Key, Value)
00403 
00404    static inline long size(const qx::QxCollection<Key, Value> & t)                        { return static_cast<long>(t.size()); }
00405    static inline void clear(qx::QxCollection<Key, Value> & t)                             { t.clear(); }
00406    static inline void reserve(qx::QxCollection<Key, Value> & t, long l)                   { t.reserve(l); }
00407    static inline type_item createItem()                                                   { return type_item(type_item::newKey(), type_item::newValue()); }
00408    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())); }
00409    static inline type_iterator end(qx::QxCollection<Key, Value> & t)                      { return t.end(); }
00410 
00411    static inline type_iterator begin(qx::QxCollection<Key, Value> & t, type_item & item)
00412    { if (t.size() <= 0) { return t.end(); }; item.value(t.getByIndex(0)); item.key(t.getKeyByIndex(0)); return t.begin(); }
00413 
00414    static inline type_iterator next(qx::QxCollection<Key, Value> & t, type_iterator itr, type_item & item)
00415    { 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; }
00416 
00417 };
00418 
00419 } // namespace trait
00420 } // namespace qx
00421 
00422 #endif // _QX_GENERIC_CONTAINER_H_