none
C++ std::set<>.find()の返値の固定 RRS feed

  • 質問

  • VS2010というよりはC++に関する質問ですがおわかりになった方がいらっしゃったらお教えください。

    環境:VS2010SP1

    ソースは以下のようになります。(*ietm) += my;で「error C2678: 二項演算子 '+=' : 型 'const MyClass' の左オペランドを扱う演算子が見つかりません (または変換できません) (新しい動作; ヘルプを参照)。」というメッセージが出ます。どうもthis->list.find(my)の返すイテレータがconst_iteratorのようです。通常のイテレータで返して欲しかったのですが、両者を区別するコントロールが分かりませんでした。const_castで外そうとするとitemはMyClassのポインタではなくset<MyClass>のイテレータでconst_cast<>の<>内でstd::を使用することができません(理由は分かっていません)。

    このようなとき、+=演算子を使用するためにはどのようにすればよろしいでしょうか。findがconstでないイテレータを返すようにできれば良いのですが。

    #pragma once
    class MyClass
    {
    public:
    	MyClass(void);
    	virtual ~MyClass(void);
    	int test_;
    	MyClass operator+(const MyClass& rhs) const {
    		MyClass rvalue;
    		rvalue.test_ = this->test_ + rhs.test_;
     
    		return rvalue;
    	}
    	MyClass& operator=(const MyClass& rhs) {
    		test_ = rhs.test_;
     
    		return (*this);
    	}
    	MyClass& operator+=(const MyClass& rhs) {
    		this->test_ = rhs.test_;
     
    		return (*this);
    	}
    };

    #include"MyClass.h"#include<set>usingnamespace std; class MyClassList { public: MyClassList(void); virtual ~MyClassList(void); private: set<MyClass> list; public: virtualint insert(const MyClass& my); };

    int MyClassList::insert(const MyClass& my)
    {
    	std::set<MyClass>::iterator item;
    	this->list.insert(my);
    	item = this->list.find(my);
    	if (list.end() != item) {
    		(*item) += my;
    	}
    	return 0;
    }


    from Microsoft TechNet

    2012年2月23日 7:27

回答

すべての返信

  • Connectにも報告はありますが、"By Design"だそうです。setのあずかり知らぬところでキーが変わってしまうと、setが破綻するからとかなんとか。
    そのあたりを承知の上で、「クラスのメンバ中の、キーに参与しない部分だけ書き換えるんだヨ」という向きには、const_castを使えばいいです。
    const_cast<MyClass&>(*item) += my;
    (ただ、このサンプル的なMyClassだと、どう考えてもキーを書き換えていることになるのでまずいですが)

    http://connect.microsoft.com/VisualStudio/feedback/details/532300/std-set-t-iterator-and-std-set-t-const-iterator-are-the-same-type-breaks-code

    http://blogs.msdn.com/b/vcblog/archive/2009/05/25/stl-breaking-changes-in-visual-studio-2010-beta-1.aspx


    jzkey

    • 回答としてマーク KMURA 2012年2月24日 2:54
    2012年2月24日 2:03
  • ご回答ありがとうございます。実際に使用しているものはキーに関与していない部分ですので問題ないようですね。早速試してみます。ありがとうございました。


    from Microsoft TechNet

    2012年2月24日 2:56
  • 解決になってるようなので、どうしようかとも思ったんですが、あまりにもタイムリーだったので張っておきます。http://codezine.jp/article/detail/6186

    参考になると思います。

    あと、キーの部分が変わらないのなら、set ではなく、map はだめなの?という気もしますけど。。。


    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/

    2012年2月24日 15:13
  • 参考ページありがとうございます。

    vectorは考慮に値すると思います。

    mapは当方の理解が正しければ、格納されるクラスと別にKeyを指定してやる必要があったと思いますので、クラス内に既に定義済みのKeyを抜き出すのが不要と判断したことと、operator<が少し面倒な判断基準ですので(クラス内定義済み)同定義を2重に持ちたくないという判断に基づいております。ご返信ありがとうございました。


    from Microsoft TechNet

    2012年2月25日 1:04
  • mapはキーと値のペアで保持されるコレクションクラスなので、基本的には別々です。もちろん、map<MyClass,MyClass>として、キー部分はキーのものだけ、利用するというやり方もあります(ただし、実行コストは増えます)。

    悪い意味で動けばいいというのならそういう実装もありです。


    わんくま同盟,Microsoft MVP for Visual C++(Oct 2005-) http://blogs.wankuma.com/tocchann/

    2012年2月25日 6:46