• 締切済み

新たに定義したクラスでmapを作成する場合

STLのmapを使っているのですが、自分で定義したクラス(便宜上Keyと書きます)をキーにすると想定した動作になりません。 insert、iteratorによる参照はできるのですが、findがうまくいっていないようです。 値を見ると探しているキーと同じものが入っているのですが、2つのKeyのインスタンスが同一であるということが認識されていないのかfindの結果は(mapの名前).end()になってしまいます。 Keyのオペレータとして'<'は定義しましたが、「同一である」ことを示すために別のオペレータを定義する必要があるのでしょうか? あてずっぽうで'=='を定義してみましたがうまくいきません。 お知恵を拝借できればと思います。よろしくお願いします。

みんなの回答

  • KoHal
  • ベストアンサー率60% (110/181)
回答No.1

具体的にソースを見ないと何も分かりません。 問題が発生する最低限のソースを補足で提示してください。 あてずっぽうで1つ言うと Keyのポインタをmapのキーにしていて、Keyの値で検索しているつもりが、実はKeyのアドレスで検索されていた というのがありがちなポカですが。それは大丈夫ですか?

hime-ichigo
質問者

お礼

ご回答ありがとうございます。 かなり大きなプログラムの一部なので掲載しづらかったのですが、今補足を掲載しようとして最低限の部分だけ抜き出してみたところちゃんと動きました。 全体ではまだどこがおかしいのか分かりませんが、クラス定義とは別の部分に問題があるようですのでもう少し調べてみます。 よく確かめずに質問してしまって大変申し訳ありませんでした。

関連するQ&A

  • STLのmapのキーの変更方法

    // この時点でキーは"1,2,3,4,5"と並んでいる std::map< CString , int >::iterator it = m_mapNOKATA.find("3"); if( it != m_mapNOKATA ) { (*it).first = "9"; } というような使い方は出来るのでしょうか? また、これをした場合、 for( it = m_mapNOKATA.begin() ; it != m_mapNOKATA.end() ; ++it) { cout << (*it).first << endl; } とすると、結果は 1 2 4 5 9 となるのか、 1 2 9 4 5 となるのでしょうか? 上の結果が正しいように思えますが、だとしたら、キーを変更した時点で並べ替えが起きている? それとも、キーはinsert後はもう変更できなくて、erase→insertとしなくてはならないのでしょうか? 手元にSTL環境が無いので、確認できません。 どなたかお分かりの方がいらっしゃいましたら教えてください。 たぶん、multimapやsetでも結果は同じかと思います。

  • mapによるkeyとvalueのinsertに失敗しております。

    STLのmapコンテナにて、 valueを取得したり、 keyとvalueを登録するソースを書いていました。 get(key)にあたって、 valの取得に失敗した際には、 mapコンテナ上のkey-valueデータと 同期されているMySQLより、 データを取得してきます。 MySQLよりkeyに対応するvalの取得が 完了したら、 そのkeyとvalをmapコンテナに insertしたいと思っています。 つきまして、 insertを行おうと、 「_container.insert(std::make_pair(key, val));」の一文を ソースに挿入したところ、 「型が違う!」という内容(?)のエラー文で コンパイル時に怒られてしまいました。 ただ、「どの様に直してごらん!」と エラー文が言っているのか、 今いち、意味を理解できないでいます。 このエラー情報的には、 どんな風の型の改善を求められているのでしょうか? 教えていただけるとありがたいです。 もし可能でしたら、pointBの 「_container.insert(std::make_pair(key, val));」の部分で、 MySQLから取得済みkeyとvalを、 pointAのkeyとvalに代入する方法も 教えていただけるとありがたいです。 どちらかでも、 アドバイスをいただけますとありがたいです。 どうぞ宜しくお願い致します。 -------------------------------------------------- template<typename KEY, typename VALUE> class hoge : public service_object<ipl<KEY, VALUE>> { virtual void put(key_type key, value_type val) { _container.insert(std::make_pair(key, val)); // pointA } virtual cc::fu<value_type> get(key_type key) { typename container_type::iterator iterator = _container.find(key); if (iterator != _container.end()) { return cc::fu<value_type>((*iterator).second); }else { //getにした場合MySQLよりkeyとvalueを取得完了できるので取得した。 /* MySQLより取得したkeyとvalをpointAのようにmapコンテナにinsertしたい。*/ _container.insert(std::make_pair(key, val)); //pointB  } } }; -------------------------------------------------- ■エラー文 error: conversion from std::pair<std::_Rb_tree_iterator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, boost::shared_ptr<csx::basic_message_cons<csx::basic_message<void, char> > > > >, bool>’ to non-scalar type ‘csrpc::future<boost::shared_ptr<csx::basic_message_cons<csx::basic_message<void, char> > > >’ requested

  • map::find()の戻り値が変数に入ってくれません。

    こんにちは、boundaryといいます。 ユーザー型のキーとユーザー型の値をmapに挿入したのです が、map::find()の戻り値が変数に入ってくれません。 operator=を定義しないといけないのかなと思いやってみた のですがうまくいきません。 std::map<ユーザー型,ユーザー型>::iteratorを定義しない といけないのでしょうか? どなたかお知恵をお貸しください。 よろしくおねがいします。 windows2000 vc6.0sp5 ps.ソースコードを載せようとしたのですが、質問文字数が 最長文字数を超えるようで質問する事ができません。 ですのでかなり端折っています。(スミマセン) /* mapのキーです。 */ typedef struct _StateAndReturn { int State; int Return; } StateAndReturn; /* mapの値です。 */ struct NextStateAndFunc { NextStateAndFunc& operator=(const NextStateAndFunc& X){ NextState = X.NextState; MemFuncPointer = X.MemFuncPointer; } typedef int (Funcs::*pFunc)(); int NextState; pFunc MemFuncPointer; }; class CEventMap { private: typedef int (Funcs::*pFunc)(); typedef map<StateAndReturn, NextStateAndFunc, my_less> _EventFuncMap; _EventFuncMap EventFuncMap; public: void Set(int StateNow, int ServerReturnCode, int StateNext, pFunc pF) { /*登録します。*/ } const NextStateAndFunc Answer(int StateNow, int ServerReturnCode) { StateAndReturn tempStateAndReturn; tempStateAndReturn.State = StateNow; tempStateAndReturn.Return = ServerReturnCode; map<StateAndReturn, NextStateAndFunc>::const_iterator ite; ite = EventFuncMap.find(tempStateAndReturn); /* ←ここでエラーになります。 */ return ite->second; } };

  • map(STL)でinsertを行いたいですが、成功できないでいます。

    皆さん、こんにちは。 このほど、STLのMAPを勉強しだしたものですが、 もっと基本的な、 C++の事でつまずいてしまいました。 keyとvalueのセットを 登録したり、 取得したりするソースを書いています。 下記ソースにありますとおり、 getの指示を出した際は、 通常、find(key)を行い、 valueを得るのですが、 仮にfindにて意図するvalueが見つからなかった場合には、 MySQLから意図するkeyに対応するvalueを 取ってこようと思っています。 そして、MySQLからvalueを取得した後は、 「m1.insert」にて 取得したその「value」と「key」のセットを insertを行う事で、 コンテナに登録作業をしたいつもりなのです。 どんな1行を足せばいいでしょうか? ずばりの答えでなく、 ユルメな方針のアドバイスでも いただけるとありがたいです。 ================================================================= virtual void put(key_type key, value_type val) { m1.insert(std::make_pair(key, val)); } virtual void get(key_type key) { typename container_type::iterator iterator = m1.find(key); if (iterator != m1.end()) { CTL_INFO("", "[info] Got the value ."); } else { /* ここでMySQLへ接続を行う*/ char query[256]; std::stringstream keystream ; keystream << key; std::string key1 = keystream.str().c_str(); if(sprintf(query, "select value_dht from table_name where key = ('%s')",keystream.str().c_str())); mysql_query(conn, query); res = mysql_use_result(conn); //get the results while ((row = mysql_fetch_row(res)) != NULL){ std::stringstream keydb2stream ; key2stream << row[0] ; std::string val1 = key2stream.str().c_str(); } /* ここで、MySQLから得たvalについて、      上記「virtual void put」のように「m1.insert」を行いたい。 それにより、returnで再度virtual void getへ移動した際には、     「m1.find(key)」を成功させたいです。*/ } return 0; }; ================================================================= また、間違っているかもしれませんが、 試しに、 「return 0」の2行上で、 次の1行を入れてみたのですが、 コンパイル時にエラーが出て怒られて失敗をしてしまいました。 「virtual void put」の部分で行っているinsertと、 同じ内容の文字列を同じようにinsertしているのに、 今回は怒られてしまうのかも、 よく分かりませんでした。 的外れな対応でしたらすいません。 ======================================================== m1.insert(std::make_pair(keystream.str().c_str(), key2stream.str().c_str())) ======================================================== error: cannot convert ‘const char*’ to ‘sc::basic_message_cons<sc::basic_message<void, char> >*’ in initialization

  • [C++]std:mapの扱いを教えて頂けますか?

    お忙し中、失礼します。 プログラミングのついて質問させて下さい。 使用言語: C++ 使用ヘッダファイル:<map> [質問] 動的確保したstd:mapを解放したいのですが、 mapの第二引数にクラスポインタを与えた場合、 登録したクラスのメンバ関数を呼び出すことは 出来るでしょうか? もし可能ならば、方法を教えて頂けないでしょうか?? 自作クラス class C; class test { //メンバ変数  private: C m_pC; //メンバ関数 public: test();     //コンストラクタ ~test();    //デストラクタ //初期化処理 void Init() { m_pC = new C(); } //終了処理   void Term() { delete m_pC; m_pC = NULL; }} }; map 定義 map< ID , test* >* pMap; マップ解放処理 std::map< ID ,test*>::iterator iterator; iterator = pMap->begin(); for(iterator ; iterator != pMap.End();iterator++) { //************************ // // ここでtestクラスの解放処理を呼び出したい // 例) test->Term() // //************************* } //マップ登録要素クリア pMap->clear(); まだ、mapの仕様が分かっておらず勉強中の身で 申し訳ないです。 助言頂ければ幸いです。 どうかよろしくお願いします。

  • 文字列のコピー

    ecoFileListに文字列をコピーしたいのですが、エラーになります。 どなたか教えて下さい int DML_Backup::searchEcoDataFileName(char (*ecoFileList)[32]) { map_type files; WIN32_FIND_DATA find_data; HANDLE handle = FindFirstFile("*.ecd", &find_data); if ( handle != INVALID_HANDLE_VALUE) { do { files.insert(map_type::value_type( find_data.ftLastWriteTime, find_data.cFileName)); } while ( FindNextFile( handle, &find_data) ); FindClose(handle); } for ( map_type::iterator iter = files.begin(); iter != files.end(); ++iter ) { lstrcpy(*ecoFileList, iter->second); ecoFileList++; } }

  • マップとアルゴリズム

    またまた質問です。 以下の処理をさせるとエラーが出ます。 どなたか見ていただけますか? 環境はWindows XP, Visual Studio.NETです。 -----処理部分------------------ map<char, int> m; for(i=0; i<10; i++){  m.insert(pair<char, int>('A'+i, i)); } reverse(m.begin(), m.end()); map<char, int>::iterator p; p = m.begin(); while( p != m.end() ){  cout << p->first << " " << p->second << endl;  p++; } ------以下エラーログ--------------- C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(16) : error C2166: 左辺値は const オブジェクトに指定されています。 C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(46) : コンパイルされたクラスのテンプレートのインスタンス化 'void std::swap<const _Ty1>(const _Ty &,const _Ty &)' の参照を確認してください with [ _Ty1=int, _Ty=int ] C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(45): クラス テンプレートのメンバ関数 'void std::pair<_Ty1,_Ty2>::swap(std::pair<_Ty1,_Ty2>::_Myt &)' のコンパイル中 with [ _Ty1=const int, _Ty2=int ] ClusteringMain.cpp(45) : コンパイルされたクラスのテンプレートのインスタンス化 'std::pair<_Ty1,_Ty2>' の参照を確認してください with [ _Ty1=const int, _Ty2=int ] C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\include\utility(16) : error C2166: 左辺値は const オブジェクトに指定されています。

  • C++ の map についてです

    C++の初心者です。よろしくお願いします。 DirectXを使っていて簡単なゲームを作っていまして、 mapを使っていると、このようなエラーが出てしまいどうしても理由わかりませんでした。 class D2DMap : public GameTexture{ protected: GameTexture** CopyTexture; int MaxMass; int WidthMass; int HeightMass; int WidthMassPixel; int HeightMassPixel; int MassInfo[30][30]; public: D2DMap(); virtual ~D2DMap(); HRESULT LoadMapTexture(int widthmass, int widthmasspixel,int heightmass, int heightmasspixel, const char* FileName, D3DCOLOR color); HRESULT LoadTextMass(const char* FileName); int GetWidthMassPixel(){ return WidthMassPixel;} int GetWidthMassNum(){ return WidthMass;} int GetHeightMassPixel(){ return HeightMassPixel;} int GetHeightMassNum(){ return HeightMass;} int GetMassInfo(int x, int y){ return MassInfo[y][x];} void DrawMap(D3DCOLOR color); void DrawCopyMap(D3DCOLOR color); void SetCopyTex(GameTexture* copy){ CopyTexture= &copy;} void Delete(){} }; map<string , D2DMap*> MapBox; と定義して string Name="--------"; D2DMap map; MapBox.insert( map<string, D2DMap*>::value_type(Name, &map)); としたとこと error C2275: 'std::string' : この型は演算子として使用できません 'std::string' の宣言を確認してください。 error C2059: 構文エラー : '>' error C2039: 'value_type' : '`global namespace'' のメンバではありません というエラーが出てきました。 mapのfind や iterator は可能なのですがinsertの場合エラー となり、理由が全く分かりません。詳しい方アドバイスをお願いしたい のですが、よろしくお願いします。 VC++2008 を使っています。

  • 新しい順のリスト取得

    この件につきましては、特定の回答者の方のおかげで収束につながりました。あとひとつだけお力をください。ファイルの古い順にリストを作成してもらいましたが、これに新しい順にソートする機能を追加したいです。これで仕様としては終わりです。どうかよろしくお願いいたします bool operator<(const FILETIME& x, const FILETIME& y) { if ( x.dwHighDateTime < y.dwHighDateTime ) return true; if ( y.dwHighDateTime < x.dwHighDateTime ) return false; return x.dwLowDateTime < y.dwLowDateTime; } class DML_Backup { public: vector<string> files_; void search(const char* spec) { typedef multimap<FILETIME,string> map_type; map_type files; WIN32_FIND_DATAA find_data; HANDLE handle = FindFirstFileA(spec, &find_data); if ( handle != INVALID_HANDLE_VALUE) { do { files.insert(map_type::value_type(find_data.ftLastWriteTime, find_data.cFileName)); } while ( FindNextFileA( handle, &find_data) ); FindClose(handle); } files_.clear(); for ( map_type::iterator iter = files.begin(); iter != files.end(); ++iter ) { files_.push_back(iter->second);         } }

  • 「第1正規化」の定義について

    はじめまして。 今までなんとなくAccessを使っていたのですが、一度きちんと勉強しておこうと思い、データベースの入門から始めているところです。 そこで、どうしても解らないところがでてきてしまいました。タイトル通り「第1正規化」についてなのですが、 http://www.kogures.com/hitoshi/webtext/db-seikika/ http://www.microsoft.com/japan/office/previous/xp/suminaka/access/database/database1_3.htm 上記最初のURL内「第1正規化」の項を参照すると、第1正規化とは 「繰り返しの部分を複数のレコードにして,繰り返しを排除する操作」 とあります。 これは、 「1レコードに繰り返しデータが存在している状態」を「非正規形」とし 「1レコードに存在する繰り返しデータを全て独立したレコードに書き出す」 事をもって「第1正規化」(第1正規形)と呼んでいるようです。 (便宜的に「定義A」と呼びます) 表を主キーで分割してはいません。 一方、以下のURLを参照すると・・・ http://sql.main.jp/cont/norm/nto1.html http://d.hatena.ne.jp/end0tknr/20080830/1220044407 http://www.techscore.com/tech/sql/SQL16/16_02.html/ 最後のURL内では、非正規形の定義は同様ですが、 「主キーによる表の分割を行い繰り返しを排除する」 事によって、「第1正規化」と呼んでいます。 (定義Bと呼びます) また、上記中段のURL内では、定義Aの状態も「非正規形」であると表現しているように読み取れます。 つまり解らない事というのは、「定義A」と「定義B」のどちらが正しい「第1正規化」(第1正規形)なのか?という事です。 Webや解説書等を漁ってみると、体感で 定義A:定義B=4:6 くらいのようで、定義Bが多いものの、かなり割れています。 個人的には、「データの重複を無くし」「汎用性を持たせる」という目的からすれば定義Bを第1正規形と扱った方が良いような気はしますが、こんなに書かれ方が分かれていると、どちらを信じて良いのか迷ってしまいます。 それとも、どちらも第1正規化の範疇なのでしょうか? 仕事上後進の指導もする事になるため、極力正確な理解をしておきたいのです。 どうか、お知恵を貸していただけないでしょうか。

専門家に質問してみよう