ページ 11

C++ setのイテレータ経由でinsertできない

Posted: 2012年8月04日(土) 14:45
by beatle
以下のコードで、なぜit経由だとinsertできず、s2経由だとinsertできるのか分かりません。
なぜコンパイルに通らないか分かる方、教えてください。

it->insertの行を有効にしてコンパイルしようとすると以下の様なコンパイルエラーとなります(clang++, g++ともにエラーになります)。
► スポイラーを表示

コード:

#include <set>
using namespace std;

void f()
{
    set<set<int>> s1;
    set<int> s2;
    set<set<int>>::iterator it;

    //it->insert(s2.begin(), s2.end()); // ERROR
    s2.insert(s2.begin(), s2.end()); // OK
}

Re: C++ setのイテレータ経由でinsertできない

Posted: 2012年8月04日(土) 17:41
by しひ
std::set::iteratorがconst_iteratorのエイリアスになっているからではないでしょうか。
恐らくsetの整合性を保つためではないかと思いますが、詳しいことは知りません。

コード:

// g++ 4.7.0
// bits/stl_set.h

// DR 103. set::iterator is required to be modifiable,
// but this allows modification of keys.
typedef typename _Rep_type::const_iterator            iterator;
typedef typename _Rep_type::const_iterator            const_iterator;

Re: C++ setのイテレータ経由でinsertできない

Posted: 2012年8月04日(土) 23:05
by beatle
返信ありがとうございます。
確かに、イテレータ経由で要素を勝手にいじられると、setの中での順番が変わらないといけないときであっても順番が変わらないまま、整合性がなくなってしまいますね。
setの中身を弄るときは erase してから insert するのが基本だよとTwitterで教えてもらいました。

どうやら iterator と const_iterator が同じ宣言になってしまっているのはバグのようですね。
103. set::iterator is required to be modifiable, but this allows modification of keys

Re: C++ setのイテレータ経由でinsertできない

Posted: 2012年9月03日(月) 15:09
by kariya_mitsuru
beatle さんが書きました:どうやら iterator と const_iterator が同じ宣言になってしまっているのはバグのようですね。
103. set::iterator is required to be modifiable, but this allows modification of keys
少なくとも C+11 では、iterator と const_iterator は同じ型でも構わないことになっています。
(リンク先にも記載がありますよ)

Re: C++ setのイテレータ経由でinsertできない

Posted: 2012年9月03日(月) 20:06
by beatle
ありがとうございます。
確かに C++11 にて associative containers の要件が修正されていますね。