3 に答える
私はあなたのアプローチを支持しているわけではありませんが、問題のイテレータとのint
間の距離である場合は、単に使用できますbegin()
c.begin() + int_value
また
std::advance(c.begin(), int_value)
イテレータを取得します。2 番目のバージョンは、ランダム アクセス イテレータではないイテレータに必要です。
個人の正気 (およびプログラムの速度) のために、何らかの形でイテレータを直接返すことをお勧めします。
これをいずれかの方法で解決できるインターフェースは多数あります。私が「古い C の方法」と呼ぶものは、out パラメータによって返されます。
bool find_stuff(stuff, container::iterator* out_iter) {
...
if(found && out_iter)
*out_iter = found_iter;
return found;
}
これを使って:
container::iterator the_iter;
if(find_stuff(the_stuff, &the_iter)) ...
また
if(find_stuff(the_stuff, 0)) // if you don't need the iterator
これは慣用的な C++ ではありませんが、Linus はこれに満足しています。
2番目に考えられる理論的に正しいバージョンはboost::optional
、値を返すようなものを使用しています。このようにして、何らかの値を返すか、何も返さないかのいずれかを返します。
boost::optional<container::iterator> find_stuff(stuff) {
...
if(found && out_iter)
return found_iter;
return boost::none;
}
使用する:
boost::optional<container::iterator> found = find_stuff(the_stuff);
if(found) {
do something with *found, which is the iterator.
}
また
if(find_stuff(the_stuff)) ...
3番目に考えられる解決策は、うまくいくでしょうstd::set::insert
。フラグと値で構成されるペアを返します。
std::pair<bool, container::iterator> find_stuff(stuff) {
...
return std::make_pair(found, found_iter);
}
使用する:
std::pair<bool, container::iterator> found = find_stuff(the_stuff);
if(found.first) ...
mulitmap<Person,Hoobby>
に変更することを検討してくださいset<pair<Person,Hobby> >
。そうすれば、現在抱えている問題はなくなります。または への変更をご検討くださいmap<Person, set<Hobby> >
。どちらのオプションでも、重複するペアを挿入できません。
趣味用と人用の 2 つのセット (マルチ セットではありません) を使用します。これら 2 つはフィルターとして機能するため、同じ人 (または趣味) を 2 回追加することはありません。これらのセットに対する挿入操作は、挿入される要素の反復子 (または、既に挿入されている場合は要素の「正しい」反復子) を提供します。hobbies_set と person_set に挿入することで得られる 2 つの反復子は、マルチマップのキーと値として使用されるようになりました
multi_map の代わりにリレーションに 3 番目のセット (multi_set ではない) を使用すると、リレーションを挿入する前にチェックする必要がないという利点があります。 . 両方の方法で、イテレータとブール値を返します(既に存在するか、追加されたかを示します)
データ構造:
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;
入れる:
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.
調べる:
// 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.