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,