Dominique Devienne <ddevienne <at> gmail.com> writes:
On Thu, Mar 3, 2016 at 10:21 AM, Joaquin M LópezMuñoz <joaquin <at>
Suppose we use the following: template<typename T,T puncture> struct punctured_less { bool operator()(const T& x,const T& y)const { if(x==puncture&&y==puncture)return true;
But can we do better? If like in any initial email, you take into account that the to-be-indexed int is part of a larger struct with other fields, which can be used to "break ties" between elements who's index match the "puncture"?
[...]
struct entry { int uid; // real uuid in reality, but enough for our needs here int occurence; // the field to be indexed, uniquely "except for -1" };
OK, yes, we can do something with that. What you want is unique sorting by occurrence, except when occurrence==-1 in which case you want to (uniquely) sort lexicographically on uid. This *is* indeed a SWO, so we can do: struct entry { int uid; int occurrence; }; struct entry_occurrence_less { bool operator()(const entry& x,const entry& y)const { if(x.occurrence==-1&&y.occurrence==-1)return x.uid<y.uid; return x.occurrence<y.occurrence; } bool operator()(const entry& x,int y)const { if(x.occurrence==-1&&y==-1)return false; return x.occurrence<y; } bool operator()(int x,const entry& y)const { if(x==-1&&y.occurrence==-1)return false; return x<y.occurrence; } }; using set=boost::multi_index_container< entry, indexed_by< ordered_unique<identity<entry>,entry_occurrence_less> > >; The following set s={ {386,-3},{29387,-2},{2323,-1},{231,0},{394857,0}, {123,1},{38274,-1},{4534,2},{234823,3},{8342,-1}, {5932,4},{12892,5},{928173,-1},{22332,6},{78172,7}, {8784734,-1},{43329,8},{545434,9},{10900,9},{33334,-1}}; for(const entry& x:s)std::cout<<x.occurrence<<" "; outputs -3 -2 -1 -1 -1 -1 -1 -1 0 1 2 3 4 5 6 7 8 9 as it should: duplicates for 0 an 9 are rejected, multiple -1s allowed. Thanks to the overloads of entry_occurrence_less::operator() we can lookup by occurrence as if we were using member<entry,int,&entry::occurence>: std::cout<<s.find(5)->uid<<"\n"; // prints 12892 and lookup on -1 also works as expected. For instance, the following for(auto r=s.equal_range(-1);r.first!=r.second;++r.first){ std::cout<<r.first->uid<<" "; } outputs 2323 8342 33334 38274 928173 8784734 I think this suits exactly your needs, please report back otherwise. Joaquín M López Muñoz