STL設定交差点と出力

VC ++ 2010でコンパイルするために、このようなコードスニペットがあります。

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

私が知る限り、これはうまくいくはずです。しかし、私はビルドエラーを取得します:

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::allocator,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::allocator,false>>>,
1>              _InIt1=std::_Tree_unchecked_const_iterator,std::allocator,false>>>,
1>              _InIt2=std::_Tree_unchecked_const_iterator,std::allocator,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>,_OutIt>(_InIt1,_InIt1,_InIt2,_InIt2,_OutIt,std::tr1::true_type)' being compiled
1>          with
1>          [
1>              _OutIt=std::_Tree_const_iterator,std::allocator,false>>>,
1>              _Mytree=std::_Tree_val,std::allocator,false>>,
1>              _InIt1=std::_Tree_unchecked_const_iterator,std::allocator,false>>>,
1>              _InIt2=std::_Tree_unchecked_const_iterator,std::allocator,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>>(_InIt1,_InIt1,_InIt2,_InIt2,_OutIt)' being compiled
1>          with
1>          [
1>              _OutIt=std::_Tree_const_iterator,std::allocator,false>>>,
1>              _Mytree=std::_Tree_val,std::allocator,false>>,
1>              _InIt1=std::_Tree_const_iterator,std::allocator,false>>>,
1>              _InIt2=std::_Tree_const_iterator,std::allocator,false>>>
1>          ]

そのために、明示的なテンプレートパラメータ宣言を行いました。

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

しかし、私は同じエラーがあります。ここでの問題は、2番目のケースでは、const_iteratorを渡すと、パラメータ型が一致しないため、const_iteratorとiteratorの間の変換エラーで失敗するはずです。私はここで何が欠けていますか? (私はset_intersectionの "inserter"形式について知っていますが、ここで何が間違っているかを知りたい)

7

3 答え

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

最後のパラメータは出力イテレータでなければなりません。あなたの場合、それは不変ではありません(さらに、 std :: set には不変要素があります)。代わりにinsert_iteratorを使うべきです:

    std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), std::inserter(res_set, res_set.end()));
11
追加された

std :: set_intersection への出力引数は、変更可能でなければなりません value_type std :: set のイテレータは突然変異をサポートしませんが、 要素の値を変更することは、要素の所在が変更される可能性があるためです セット。 std :: set_iterator を持つグループの関数が設計されています 並べ替えられたシーケンスを処理する。 std :: vector

あなたの場合、 std :: set std :: vector に置き換えるか、 必要に応じてソートします(場合によっては std :: lower_bound を使用します)。 挿入の際にソートされたままにするための挿入)、または std :: insert_iterator(res_set、res_set.end())

8
追加された
Jamesは、セットされた関数は、ソートされたベクトルで使用されるのと同じように、セットで使用されるように設計されています。セットをベクトルに変更するだけでは何も解決されません。間違っているのは、書き込めない最後のパラメータだけです。挿入イテレータは、セットまたはベクトルに対してそれを修正します。
追加された 著者 Rob Kennedy,
std :: set は実際には数学的な意味での集合ではありません。少なくとも、それは部分的にしかありません。一般に、コンピュータサイエンスでは、セットは、重複がなく、多かれ少なかれ迅速なルックアップを持つ単純な順序付けされていないコレクションです。 std :: set は順序を追加しますが、それ以外の場合はこの定義を満たします。 (パスカルは数学的な意味でセットを持っていましたが、小さな整数に限定されていました。 std :: bitset のようなものです)。
追加された 著者 James Kanze,
@RobKennedyそれはもう一つの問題です: std :: vector では、 res_set.resize(s1.size()+ s2.size())のようなものを書くことができます。 res_set.end()、res_set.erase()、res_set.begin()、res_set.begin()、res_set.erase() 。とにかく、 s1`と s2 の制約は、データをソートすることだけです: std :: set を使用すると、最もシンプルでベスト)が、唯一の方法ではありません。
追加された 著者 James Kanze,
記録のために、私は2つのセットの交点が些細な形でなければならないと考えていました。私は、デフォルトでセットを扱う交差法はないことに少し驚いています。私は何かを逃したのか、それはSTLの欠点です。
追加された 著者 progician,

res_set.begin() can't be used as the output argument of set_intersection for two reasons:

  • セットが空であり、セットの既存の要素を上書きしようとします。
  • セットの要素を変更することはできません。

代わりに、新しい要素をセットに挿入する insert_iterator が必要です。

std::set_intersection(s1.begin(), s1.end(), s2.begin(), s2.end(), 
                      std::inserter(res_set, res_set.end()))
8
追加された