template<typename TPOD>
CDataCache & operator << (CDataCache &dc, const TPOD & d)
{
    dc.PushData(&d, sizeof(TPOD));
    return dc;
}

template<typename TPOD>
CDataCache & operator >> (CDataCache &dc, TPOD & d)
{
    dc.ReadData(&d, sizeof(TPOD));
    return dc;
}

template<typename TPOD>
void CachePODData(CDataCache &dc, const std::vector<TPOD> & d)
{
    size_t ttl_items = d.size();
    dc << ttl_items;
    
    if (ttl_items > 0)
    {
        const TPOD * pHeader = &*d.begin();
        dc.PushData(pHeader, ttl_items * sizeof(TPOD));
    }
}

template<typename TPOD>
void RestorePODData(CDataCache &dc, std::vector<TPOD> & d)
{
    size_t ttl_items = 0;
    d.clear();
    dc >> ttl_items;
    if (ttl_items > 0)
    {
        d.insert(d.end(), ttl_items, TPOD{});
        TPOD * pHeader = &*d.begin();
        dc.ReadData(pHeader, ttl_items * sizeof(TPOD));
    }
}

template<typename TPOD>
void CachePODData(CDataCache &dc, const std::list<TPOD> & d)
{
    size_t ttl_items = d.size();
    dc << ttl_items;
    if (ttl_items > 0)
        for (const TPOD & v : d)
            dc << v;
}

template<typename TPOD>
void RestorePODData(CDataCache &dc, std::list<TPOD> & d)
{
    size_t ttl_items = 0;
    d.clear();
    dc >> ttl_items;
    while (ttl_items > 0)
    {
        auto iter = d.emplace(d.end());
        dc >> *iter;
        --ttl_items;
    }
}

template<typename TKEY, typename TPOD>
void CachePODData(CDataCache &dc, const std::map<TKEY, TPOD> & d)
{
    size_t ttl_items = d.size();
    
    dc << ttl_items;
    for (const auto & v : d)
    {
        dc << v.first << v.second;
    }
}

template<typename TKEY, typename TPOD>
void RestorePODData(CDataCache &dc, std::map<TKEY, TPOD> & d)
{
    size_t ttl_items = 0;
    d.clear();
    dc >> ttl_items;
    
    while (ttl_items > 0)
    {
        TKEY key;
        TPOD data;
        
        dc >> key >> data;
        
        d.emplace(std::move(key), std::move(data));
        
        --ttl_items;
    }
}

template<typename TKEY, typename TPOD, template<typename D, typename A = std::allocator<D> > class C>
void CachePODDataMMap(CDataCache &dc, const std::map<TKEY, C<TPOD> > &d)
{
    size_t ttl_items = d.size();
    
    dc << ttl_items;
    for (const auto & v : d)
    {
        dc << v.first;
        CachePODData(v.second);
    }
}

template<typename TKEY, typename TPOD, template<typename D, typename A = std::allocator<D> > class C>
void RestorePODDataMMap(CDataCache &dc, std::map<TKEY, C<TPOD> > &d)
{
    size_t ttl_items = 0;
    d.clear();
    
    dc >> ttl_items;
    
    while (ttl_items > 0)
    {
        TKEY key;
        
        dc >> key;
        auto iter = d.emplace(key, C<TPOD>{}).first;
        
        RestorePODData(dc, iter->second);
        
        --ttl_items;
    }
}

template<typename TCACHEABLE, template<typename D, typename A = std::allocator<D> > class C >
void CacheArray(CDataCache &dc, const C<TCACHEABLE> & d)
{
    size_t ttl_items = d.size();
    dc << ttl_items;
    if (ttl_items > 0)
        for (const auto & v : d)
            v.SaveToCache(dc);
}

template<typename TCACHEABLE, template<typename D, typename A = std::allocator<D> > class C >
void RestoreArray(CDataCache &dc, C<TCACHEABLE> & d)
{
    size_t ttl_items = 0;
    d.clear();
    dc >> ttl_items;
    while (ttl_items > 0)
    {
        auto iter = d.emplace(d.end());
        iter->RestoreFromCache(dc);
        --ttl_items;
    }
}

template<typename TKEY, typename TCACHEABLE>
void CacheMap(CDataCache &dc, const std::map<TKEY, TCACHEABLE>  & d)
{
    size_t ttl_items = d.size();
    
    dc << ttl_items;
    for (const auto & v : d)
    {
        dc << v.first;
        v.second.SaveToCache(dc);
    }
}

template<typename TKEY, typename TCACHEABLE>
void RestoreMap(CDataCache &dc, std::map<TKEY, TCACHEABLE>  & d)
{
    size_t ttl_items = 0;
    d.clear();
    dc >> ttl_items;
    
    while (ttl_items > 0)
    {
        TKEY key;
        dc >> key;
        
        auto iter = d.emplace(std::move(key), TCACHEABLE()).first;
        iter->second.RestoreFromCache(dc);
        --ttl_items;
    }
}

template<typename TKEY, typename TCACHEABLE, template<typename D, typename A = std::allocator<D> > class C>
void CacheMMap(CDataCache &dc, const std::map<TKEY, C<TCACHEABLE> > & d)
{
    size_t ttl_items = d.size();
    
    dc << ttl_items;
    
    for (const auto & v : d)
    {
        dc << v.first;
        CacheArray(dc, v.second);
    }
}

template<typename TKEY, typename TCACHEABLE, template<typename D, typename A = std::allocator<D> > class C>
void RestoreMMap(CDataCache &dc, std::map<TKEY, C<TCACHEABLE> >  & d)
{
    size_t ttl_items = 0;
    d.clear();
    
    dc >> ttl_items;
    
    while (ttl_items > 0)
    {
        TKEY key;
        
        dc >> key;
        auto iter = d.emplace(key, C<TCACHEABLE>{}).first;
        
        RestoreArray(dc, iter->second);
        
        --ttl_items;
    }
}

template <typename TCOMPSTORE>
void CacheCompactStore(CDataCache &dc, const TCOMPSTORE &d)
{
	std::vector< typename TCOMPSTORE::CONST_DATA_PTR > ptrvec;
	
	d.CreatePtrVector(ptrvec);
	size_t ttlItems = ptrvec.size();
	dc << ttlItems;
	//dc.PushData(&ttlItems, sizeof(size_t));
	for (auto v : ptrvec)
		v->SaveToCache(dc);
}

template <typename TCOMPSTORE>
void RestoreCompactStore(CDataCache &dc, TCOMPSTORE &d)
{
	size_t ttlItems = 0;
	d.Reset();
	dc >> ttlItems;
	//dc.ReadData(&ttlItems, sizeof(size_t));
	for (size_t i = 0; i < ttlItems; ++i)
	{
		typename TCOMPSTORE::TDATA *ptr = d.Append(typename TCOMPSTORE::TDATA());
		ptr->RestoreFromCache(dc);
	}
}

/////
/////template<typename TDOMSTORE, typename TCLSTORE>
/////CDataCache & operator << (CDataCache &dc, const TFlatDomClusterMap<TDOMSTORE, TCLSTORE> &d)
/////{
/////	dc << d.m_cdstore;
/////	dc << d.m_clstore;
/////	return dc;
/////}
/////
/////
/////template<typename TDOMSTORE, typename TCLSTORE>
/////CDataCache & operator >> (CDataCache &dc, TFlatDomClusterMap<TDOMSTORE, TCLSTORE> &d)
/////{
/////	d.m_cdstore.Reset();
/////	d.m_clstore.Reset();
/////	dc >> d.m_cdstore;
/////	dc >> d.m_clstore;
/////	
/////	d.RefreshIndices();
/////	return dc;
/////}



