Well, i once had a similar situation. One thing that came in my mind was 'can i use multi-keys'? I googled for a while, and found a sample using std::set. So, if you do not have access to boost (i recommend it, there is no point re-inventing the wheel); you can try something like the below example. I think you can use the secondary key as the position of insertion (auto-increment). From the example that i found on internet; i tailored it for my needs. This one is a modified version of the same.
Cavaet: It is using macros. I know they are evil in general, but this use is o.k. i guess.
#include <set>
#include <functional>
#include <iostream>
#include <algorithm>
#include <iterator>
#include <string>
#define MULTIKEYDEF(NAME,TYPE) \
inline TYPE const & NAME() const { return d_##NAME; } \
inline void NAME(TYPE const & t) { d_##NAME = t; } \
TYPE d_##NAME; \
class T##NAME \
: public std::unary_function<Tmultikey*,bool> { \
private: \
TYPE d_compare; \
public: \
T##NAME(TYPE t) : d_compare(t) {} \
T##NAME(T##NAME const & self) \
: d_compare(self.d_compare) {} \
bool operator()(Tmultikey * mk) { \
return d_compare == mk->##NAME(); \
} \
inline TYPE const& name() const { return d_compare; } \
}
class Tmultikey {
public:
// Actual keys
// Can be accessed through d_primary and d_secondary,
// or primary() and secondary()
MULTIKEYDEF(primary , std::string);
MULTIKEYDEF(secondary, unsigned int);
// Mandatory
bool operator < (Tmultikey const& mk) const {
if(primary() < mk.primary()) return true;
else if(primary() == mk.primary()) {
return secondary() < mk.secondary();
}
return false;
}
// Constructor
Tmultikey(std::string p, unsigned int s)
: d_primary(p), d_secondary(s) {}
// Eraser for std::set
template<typename Compare>
static void erase(std::set<Tmultikey> & c, Compare op) {
typename std::set<Tmultikey>::iterator pos = c.begin();
while(pos != c.end()) {
if(op(&(*pos))) {
c.erase(pos++);
} else ++pos;
}
}
// Eraser for std::set
template<typename Compare>
static std::set<Tmultikey>::iterator find_ex(std::set<Tmultikey> & c, Compare op) {
typename std::set<Tmultikey>::iterator pos = c.begin();
while(pos != c.end()) {
if(op(&(*pos))) {
break;
} else ++pos;
}
return pos;
}
};
int main(int argc, char* argv[])
{
std::set<Tmultikey> mkset;
mkset.insert(Tmultikey("1",5));
mkset.insert(Tmultikey("6",4));
mkset.insert(Tmultikey("3",7));
mkset.insert(Tmultikey("1",6));
std::set<Tmultikey>::iterator bg = mkset.begin();
for (;bg != mkset.end(); ++bg)
{
std::cout<<(*bg).primary()<<std::endl;
}
Tmultikey::erase(mkset,Tmultikey::Tsecondary(4));
//Tmultikey::erase(mkset,Tmultikey::Tprimary("1"));
std::cout<<"After erase ....\n";
bg = mkset.begin();
for (;bg != mkset.end(); ++bg)
{
std::cout<<(*bg).primary()<<std::endl;
}
bg = mkset.find(Tmultikey("3",7));
if (bg != mkset.end())
{
std::cout<<"Absolute Find:"<<(*bg).primary()<<" "<<(*bg).secondary()<<std::endl;
}
//bg = Tmultikey::find_ex(mkset,Tmultikey::Tprimary("1"));
bg = Tmultikey::find_ex(mkset,Tmultikey::Tsecondary(5));
if (bg != mkset.end())
{
std::cout<<"Partial Find:"<<(*bg).primary()<<" "<<(*bg).secondary()<<std::endl;
}
else {
std::cout<<"Partial Find: FAILED\n";
}
return 0;
}
HTH,