C ++ STL: recherche sur carte par itérateur sur une autre carte
Question
J'essaie de franchir des obstacles pour organiser les données d'une manière particulière. J'inclus un morceau de code simplifié qui illustre ma douleur.
Je ne peux pas utiliser de boost. J'utilise la dernière version de g ++ dans cygwin.
#include <iostream>
#include <map>
using namespace std;
int main () {
map< int,int > genmap;
map< int,int >::iterator genmapit;
map< map<int,int>::iterator,int > itermap;
// insert something into genmap
genmap.insert (make_pair(1,500) );
// find and return iterator.
genmapit=genmap.find(1);
// insert the iterator/int into itermap. Dies on each of the following 3 versions of this line.
//itermap[genmapit] = 600; // crash
//itermap.insert ( pair< map<int,int>::iterator,int >(genmapit,600) ); // crash
itermap.insert ( make_pair(genmapit,600) ); // crash
return 0;
}
Comme vous pouvez le constater, j’ai une carte simple, un itérateur de cette carte et une autre carte contenant le premier argument en tant qu’itérateur de la première carte.
Cela ressort clairement de ceci: Pourquoi ne puis-je pas insérer d'itérateur dans la carte? Que je puisse avoir un itérateur comme deuxième argument. Cependant, la manière montrée ci-dessus fournit ceci:
$ make
g++ -c -o main.o main.cpp
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_function.h: In member fun
ction `bool std::less<_Tp>::operator()(const _Tp&, const _Tp&) const [with _Tp =
std::_Rb_tree_iterator<std::pair<const int, int> >]':
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_tree.h:871: instantiate
d from `std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _All
oc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::i
nsert_unique(const _Val&) [with _Key = std::_Rb_tree_iterator<std::pair<const in
t, int> >, _Val = std::pair<const std::_Rb_tree_iterator<std::pair<const int, in
t> >, int>, _KeyOfValue = std::_Select1st<std::pair<const std::_Rb_tree_iterator
<std::pair<const int, int> >, int> >, _Compare = std::less<std::_Rb_tree_iterato
r<std::pair<const int, int> > >, _Alloc = std::allocator<std::pair<const std::_R
b_tree_iterator<std::pair<const int, int> >, int> >]'
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_map.h:360: instantiated
from `std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_
Select1st<std::pair<const _Key, _Tp> >, _Compare, _Alloc>::iterator, bool> std::
map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [wit
h _Key = std::_Rb_tree_iterator<std::pair<const int, int> >, _Tp = int, _Compare
= std::less<std::_Rb_tree_iterator<std::pair<const int, int> > >, _Alloc = std:
:allocator<std::pair<const std::_Rb_tree_iterator<std::pair<const int, int> >, i
nt> >]'
main.cpp:23: instantiated from here
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_function.h:227: error: no
match for 'operator<' in '__x < __y'
make: *** [main.o] Error 1
" instancié à partir d’ici " ne me dit rien et une recherche sur le Web ne me donne aucune information à ce sujet.
Est-ce que STL: map ne permet tout simplement pas cela? Je peux recoder mon application pour contourner ce problème, mais ce sera très inefficace et j'aimerais que cela fonctionne. Existe-t-il un autre type de pointeur que je peux créer pour un élément de carte que je pourrais utiliser?
Merci de votre temps.
La solution
Vous ne pouvez pas faire cela car std::map
les itérateurs ne sont pas des itérateurs à accès aléatoire, ils ne sont donc pas comparables avec <
.
Au lieu de cela, vous pouvez utiliser des pointeurs sur le type valeur (value_type) de la première carte en tant que clé de carte.
Autres conseils
Vous devez apprendre à lire les messages d'erreur. En particulier, regardez le message qui suit la longue description où l'erreur est survenue:
/usr/lib/gcc/i686-pc-cygwin/3.4.4/include/c++/bits/stl_function.h:227: error: no match for 'operator<' in '__x < __y'
Les itérateurs de carte ne sont pas comparables avec les opérateurs inférieurs à ceux utilisés par défaut par la carte.
Je suppose que vous pouvez fournir une fonction de comparaison qui compare les paires pointées par l'itérateur, car les itérateurs eux-mêmes ne peuvent pas être facilement comparés de manière significative.
struct CompareIterator
{
template <class FirstIter, class SecondIter>
bool operator()(FirstIter lhv, SecondIter rhv) const
{
return *lhv < *rhv;
}
};
//usage with map:
map< map<int,int>::iterator,int, CompareIterator > itermap;
std::pair
définit operator<
. J'ai également utilisé deux types d'itérateurs, car il est possible que les types soient différents (iterator
et const_iterator
)
map<Key, Value>
L'élément map
iterator
en tant qu'élément clé dans un autre operator <
n'est pas possible car Key
s'attend à ce que map iterator
soit défini par défaut sur la clé. Si le <=> (dans ce cas <=>) n'est pas défini, vous devez passer un foncteur en tant que fonction de prédicat qui fournit la comparaison de Key (itérateur de carte).