Container with iterator of list - maintain natural order with another specific order
I searched comp.lang.c++.moderated and couldn't find a solution for
this problem:
Often, it is necessary to maintain a container which must be kept in
order of insertion but also searched for a specific value. If we store
a std::list iterator in a unordered_map, this is possible. A possible
solution is attached (uses 0X). Only a const_iterator is implemented,
to keep this post short.
#pragma once
#include <unordered_map>
#include <vector>
#include <list>
#include <iostream>
using namespace std;
/* this is a const_iterator to travel along a bmap */
template<typename T>
struct slistit
{
public:
slistit(const typename list<T>::const_iterator& rhs):index(rhs){}
slistit(const slistit<T>& rhs):index(rhs.index){}
bool operator==(const slistit&rhs) const
{
return index==rhs.index;
}
bool operator!=(const slistit&rhs) const
{
return index!=rhs.index;
}
T operator*() const
{
return *index;
}
typename list<T>::const_iterator & operator++() // prefix
{
++index;
return index;
}
typename list<T>::const_iterator operator++(int gash) // postfix
{
typename list<T>::const_iterator tmp=index;
index++;
return tmp;
}
protected:
typename list<T>::const_iterator index;
};
/* this is a bmap: a combination of a sorted and non-sorted list */
template<typename T>
struct slist
{
protected:
friend struct slistit<T>;
unordered_map<T,typename list<T>::iterator > m;
list<T> n;
public:
typedef slistit<T> const_iterator;
bool empty() const
{
return n.empty();
}
unsigned size() const
{
return n.size();
}
slist(){}
~slist()
{
n.clear();
m.clear();
}
slist(const slist<T>&rhs)
{
n=rhs.n;
for(auto it=n.begin();it!=n.end();++it)
m[*it]=it;
}
slist<T>& operator=(const slist<T>&rhs){
if(this!=&rhs)
{
n.clear();
m.clear();
n=rhs.n;
for(auto it=n.begin();it!=n.end();++it)
m[*it]=it;
}
return(*this);
}
bool operator==(const slist<T>&rhs)
{
if(this!=&rhs)
{
if(n.size()==rhs.n.size())
{
auto it=m.begin();
auto jt=rhs.m.begin();
for(;(it!=m.end())&&(jt!=rhs.m.end());it++,jt++)
{
if(it->first!=jt->first)return(false);
}
}
else
return(false);
}
return(true);
}
bool operator!=(const slist<T>&rhs)
{
return(!*this==rhs);
}
bool operator<(const slist<T>&rhs)
{
if(this!=&rhs)
{
if(n.size()==rhs.n.size())
{
auto it=m.begin();
auto jt=rhs.m.begin();
for(;it!=m.end()&&jt!=rhs.m.end();it++,jt++)
{
if(it->first<jt->first)return(true);
if(it->first>jt->first)return(false);
}
}
else
return(n.size()<rhs.n.size());
}
return(false);
}
void insert(const T& t)
{
if(m.find(t)==m.end())
{
n.push_back(t);
auto it=n.end();
it--;
m[t]=it;
}
}
void erase(const T& t)
{
if(m.find(t)!=m.end())
{
auto it=m[t];
n.erase(it);
m.erase(t);
}
}
void replace(const T& told,const T& tnew)
{
if(m.find(told)!=m.end())
{
auto it=m[told];
*it=tnew;
m[tnew]=it;
m.erase(told);
}
}
void clear()
{
n.clear();
m.clear();
}
const_iterator begin() const
{
return const_iterator(n.begin());
}
const_iterator end() const
{
return const_iterator(n.end());
}
vector<T> tovector() const
{
vector<T> res;
for(auto it=n.begin();it!=n.end();++it)
res.push_back(*it);
return(res);
}
vector<T> tosortedvector() const
{
vector<T> res;
for(auto it=m.begin();it!=m.end();++it)
{
res.push_back(it->first);
}
return res;
}
};
template<typename T>
ostream& operator<<(ostream&os,const slist<T>& rhs)
{
os<<rhs.size()<<" ";
for(auto it=rhs.begin();it!=rhs.end();++it)
os<<*it<<" ";
os<<endl;
return(os);
}
template<typename T>
istream& operator>>(istream&is,slist<T>& rhs)
{
rhs.clear();
unsigned size;
is>>size;
for(unsigned it=0;it!=size;++it)
{
T val;
is>>val;
rhs.insert(val);
}
return(is);
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]