7 votes

L'intersection des ensembles STL et la sortie

J'ai un extrait de code comme celui-ci, qui doit être compilé sous VC++ 2010.

        std::set<int> s1;
        std::set<int> s2;
        std::set<int> res_set;
        std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), res_set.begin());

D'après ce que je sais, c'est censé fonctionner. Cependant, j'obtiens des erreurs de construction :

c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(4494): error C3892: 'std::_Tree_const_iterator<_Mytree>::operator *' : you cannot assign to a variable that is const
1>          with
1>          [
1>              _Mytree=std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(4522) : see reference to function template instantiation '_OutIt std::_Set_intersection<_InIt1,_InIt2,_OutIt>(_InIt1,_InIt1,_InIt2,_InIt2,_OutIt)' being compiled
1>          with
1>          [
1>              _OutIt=std::_Tree_const_iterator<std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>>,
1>              _InIt1=std::_Tree_unchecked_const_iterator<std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>>,
1>              _InIt2=std::_Tree_unchecked_const_iterator<std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(4549) : see reference to function template instantiation '_OutIt std::_Set_intersection1<std::_Tree_unchecked_const_iterator<_Mytree>,std::_Tree_unchecked_const_iterator<_Mytree>,_OutIt>(_InIt1,_InIt1,_InIt2,_InIt2,_OutIt,std::tr1::true_type)' being compiled
1>          with
1>          [
1>              _OutIt=std::_Tree_const_iterator<std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>>,
1>              _Mytree=std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>,
1>              _InIt1=std::_Tree_unchecked_const_iterator<std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>>,
1>              _InIt2=std::_Tree_unchecked_const_iterator<std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>>
1>          ]
1>          c:\p4r\pkrcode\depot\dev\stats\poker\protype\statserver\achievementmanager.cpp(175) : see reference to function template instantiation '_OutIt std::set_intersection<std::_Tree_const_iterator<_Mytree>,std::_Tree_const_iterator<_Mytree>,std::_Tree_const_iterator<_Mytree>>(_InIt1,_InIt1,_InIt2,_InIt2,_OutIt)' being compiled
1>          with
1>          [
1>              _OutIt=std::_Tree_const_iterator<std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>>,
1>              _Mytree=std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>,
1>              _InIt1=std::_Tree_const_iterator<std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>>,
1>              _InIt2=std::_Tree_const_iterator<std::_Tree_val<std::_Tset_traits<int,std::less<int>,std::allocator<int>,false>>>
1>          ]

Pour le plaisir, j'ai fait une déclaration explicite des paramètres du modèle :

std::set_intersection<std::set<int>::const_iterator, std::set<int>::const_iterator, std::set<int>::iterator>(
  s1.begin(), s1.end(), s2.begin(), s2.end(), res_set.begin()
);

Mais j'ai les mêmes erreurs. Mon problème est que dans le deuxième cas, si je passe un const_iterator, il devrait échouer avec une erreur de conversion entre const_iterator et iterator car le type de paramètre ne correspond pas. Qu'est-ce qui me manque ici ? (Je connais la forme "inserter" de set_intersection mais je veux savoir ce que je fais de mal ici).

11voto

jpalecek Points 31928
    std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), res_set.begin());

Le dernier paramètre doit être un itérateur de sortie. Dans votre cas, ce n'est pas le cas, d'autant plus qu'il est immuable (bc. std::set a des éléments immuables). Vous devriez plutôt utiliser un insert_iterator :

    std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(res_set, res_set.end()));

8voto

Mike Seymour Points 130519

res_set.begin() ne peut pas être utilisé comme argument de sortie de set_intersection pour deux raisons :

  • L'ensemble est vide, et ceci essaierait d'écraser les éléments existants de l'ensemble.
  • On ne peut pas modifier les éléments d'un ensemble.

Au lieu de cela, vous voulez un insert_iterator pour insérer les nouveaux éléments dans l'ensemble :

std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), 
                      std::inserter(res_set, res_set.end()))

8voto

James Kanze Points 96599

L'argument de sortie d'un std::set_intersection doit être vers un objet mutable value_type . Les itérateurs de std::set ne soutiennent jamais les mutations, puisque la modification de la valeur d'un élément pourrait changer sa place dans l'ensemble. l'ensemble. Les fonctions du groupe avec std::set_iterator sont conçus pour travailler sur des séquences triées, par exemple std::vector .

Dans votre cas, vous pouvez soit remplacer votre std::set avec std::vector , les trier si nécessaire (et éventuellement utiliser des std::lower_bound et pour qu'ils restent triés en fonction de l'insertion), ou utiliser std::insert_iterator( res_set, res_set.end() ) .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X