1
4

3 回答 3

3

Not that I favour your approach, but if the int is distance between begin() and the iterator in question, you can just use

c.begin() + int_value

or

std::advance(c.begin(), int_value)

to get the iterator. The second version is needed for iterators which are not random-access-iterators.

In the interest of your personal sanity (and the program's speed), I'd suggest you return the iterator directly in some form.

There are many possible interfaces that solve this one way or the other. What I would call the "old C way" would be returning by an out parameter:

bool find_stuff(stuff, container::iterator* out_iter) {
 ...
 if(found && out_iter)
   *out_iter = found_iter;
 return found;
}

use it:

container::iterator the_iter;
if(find_stuff(the_stuff, &the_iter)) ...

or

if(find_stuff(the_stuff, 0)) // if you don't need the iterator

This is not idiomatic C++, but Linus would be pleased with it.

The second possible and theoretically sound version is using something like boost::optional to return the value. This way, you return either some value or none.

boost::optional<container::iterator> find_stuff(stuff) {
 ...
 if(found && out_iter)
   return found_iter;
 return boost::none;
}

Use:

boost::optional<container::iterator> found = find_stuff(the_stuff);
if(found) {
  do something with *found, which is the iterator.
}

or

if(find_stuff(the_stuff)) ...

Third possible solution would be going the std::set::insert way, ie. returning a pair consisting of a flag and a value:

std::pair<bool, container::iterator> find_stuff(stuff) {
 ...
 return std::make_pair(found, found_iter);
}

Use:

std::pair<bool, container::iterator> found = find_stuff(the_stuff);
if(found.first) ...
于 2012-10-08T11:57:50.213 回答
2

Consider to change your mulitmap<Person,Hoobby> to set<pair<Person,Hobby> > - then you will not have problems you have now. Or consider to change to map<Person, set<Hobby> >. Both options will not allow to insert duplicate pairs.

于 2012-10-08T12:20:54.027 回答
1

Use 2 sets(not multi sets) one for hobbies and one for persons, these two acts as filters so you don't add the same person twice(or hobbie). the insert opertations on these sets gives the iterator for the element that is inserted(or the "right" iterator for element if it allready was inserted). The two iterators you get from inserting into hobbies_set and person_set are now used as key and value in a multimap

Using a third set(not multi_set) for the relation instead of a multi_map, may give the advantage of not needing to check before inserting a relation if it is allready there it will not be added again, and if it's not there it will be added. In both ways it will return an iterator and bool(tells if it was allready there or if it was added)

datastructures:

typedef std::set<Hobbie> Hobbies;
typedef std::set<Person> Persons;
typedef std::pair<Hobbies::iterator,bool> HobbiesInsertRes;
typedef std::pair<Persons::iterator,bool> PersonsInsertRes;
struct Relation {
  Hobbies::iterator hobbieIter;
  Persons::iterator personIter;
  // needed operator<(left for the as an exercies for the reader);
};
typedef set<Relation> Relations;

Hobbies hobbies;
Persons persons;
Relations relations;

insert:

HobbiesInsertRes hres = hobbies.insert(Hobbie("foo"));
PersonsInsertRes pres = persons.insert(Person("bar"));
relations.insert(Relation(hres.first, pres.first));
// adds the relation if does not exists, if it allready did exist, well you only paid the same amount of time that you would have if you would to do a check first.

lookup:

// for a concrete Person-Hobbie lookup use 
relations.find(Relation(Hobbie("foo"),Person("Bar")));

// to find all Hobbies of Person X you will need to do some work.
// the easy way, iterate all elements of relations
std::vector<Hobbie> hobbiesOfX;
Persons::iterator personX = persons.find(Person("bar"));
std::for_each(relations.begin(), relations.end(), [&hobbiesOfBar, personX](Relation r){
  if(r.personIter = personX)
    hobbiesOfX.push_back(r.hobbieIter);
});

// other way to lookup all hobbies of person X
Persons::iterator personX = persons.find(Person("bar"));  
relations.lower_bound(Relation(personX,Hobbies.begin()); 
relations.upper_bound(Relation(personX,Hobbies.end());
// this needs operator< on Relation to be implemented in a way that does ordering on Person first, Hobbie second.
于 2012-10-08T12:42:51.700 回答