質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

381閲覧

multimapの参照がうまくできない(C++)

kkkmokotan

総合スコア45

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

プログラミング言語

プログラミング言語はパソコン上で実行することができるソースコードを記述する為に扱う言語の総称です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2017/11/07 13:51

編集2017/11/07 14:19

C++のmultimapにはデータペアを削除する関数がないため、struct v tmp_vのキーに該当する部分をequal_rangeで取り出したのち、その部分からデータがtmp_v_valueに一致するものを削除するプログラムを書きました。以下にその部分のコードを掲載します。
しかしこのプログラムを実行したところ、equal_rangeのイテレータが空になってしまいました。確かにデータは追加したはずなのですが。

struct vと比較演算子の定義もコードの下に載せます。

アドバイスをお願いいたします。

C++

1/* 事前にstruct vを定義 */ 2 3multimap<struct v, struct v> *nmap = new multimap<struct v, struct v>; 4/* ------ いくつかのデータを追加。省略 ------*/ 5 6//nmapからtmp_v, tmp_v_valueのペアを持つデータのみを削除するプログラムが以下.... 7auto range = nmap->equal_range(tmp_v); //tmp_vはstruct v の変数 8for (auto it = range.first; it != range.second; ++it) { 9 if(it->second == tmp_v_value) { 10 nmap->erase(it); //tmp_v_value (tmp_v_valueはstruct vの変数)と一致したらそのイテレータを削除 11 break; 12 } 13} 14

以下に構造体の定義を追記いたします。

C++

1typedef struct v { 2 uint8_t first; 3 uint8_t second; 4 uint8_t third; 5 uint8_t fourth; 6 inline bool operator > (const struct v &i) const { 7 if (first > i.first) { 8 return true; 9 } else if(first == i.first && second > i.second){ 10 return true; 11 } else if(first == i.first && second == i.second && third > i.third){ 12 return true; 13 } else if(first == i.first && second == i.second && third == i.third && fourth > i.fourth){ 14 return true; 15 } else { 16 return false; 17 } 18 } 19 20 inline bool operator >= (const struct v &i) const { 21 if (first >= i.first) { 22 return true; 23 24 } else if(first == i.first && second >= i.second){ 25 return true; 26 27 } else if(first == i.first && second == i.second && third >= i.third){ 28 return true; 29 30 } else if(first == i.first && second == i.second && third == i.third && fourth >= i.fourth){ 31 return true; 32 33 } else { 34 return false; 35 36 } 37 } 38 39 inline bool operator < (const struct v &i) const { 40 if (first > i.first) { 41 return false; 42 } else if(first == i.first && second > i.second){ 43 return false; 44 } else if(first == i.first && second == i.second && third > i.third){ 45 return false; 46 } else if(first == i.first && second == i.second && third == i.third && fourth > i.fourth){ 47 return false; 48 } else { 49 return true; 50 } 51 } 52 53 inline bool operator <= (const struct v &i) const { 54 if (first >= i.first) { 55 return false; 56 } else if(first == i.first && second >= i.second){ 57 return false; 58 } else if(first == i.first && second == i.second && third >= i.third){ 59 return false; 60 } else if(first == i.first && second == i.second && third == i.third && fourth >= i.fourth){ 61 return false; 62 } else { 63 return true; 64 } 65 } 66 67 inline bool operator == (const struct v &i) const { 68 if (first == i.first && second == i.second && third == i.third && fourth == i.fourth) { 69 return true; 70 } else { 71 return false; 72 } 73 } 74 75 inline bool operator != (const struct v &i) const { 76 if (first != i.first || second != i.second || third != i.third || fourth != i.fourth) { 77 return true; 78 } else { 79 return false; 80 } 81 } 82}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

(あまりにコードが煩雑なため検証まで行っていませんが)struct voperator<定義が正しくない、つまりstd::multimap<Key,T>キー型Keyが満たすべき"Strict Weak Ordering"要件を満足しないように見えます。

C++標準ライブラリの連想コンテナでは「より小さい(<)」演算子の定義が最も重要です。ただし"Strict Weak Ordering"要件を正しく実装するのは非常に難しいため、<tuple>ヘッダで提供されるstd::tie関数の利用を推奨します。また、その他の大小比較演算子(>,<=,=>)定義も独自コードで行うのではなく、前述の「より小さい(<)」演算子を用いて定義すべきです。同様に、!=演算子は==演算子を用いて定義すべきです。

c++

1#include <tuple> // std::tie 2 3struct v { 4 uint8_t first; 5 uint8_t second; 6 uint8_t third; 7 uint8_t fourth; 8 9 // 大小比較演算子 10 inline bool operator<(const v& rhs) const { 11 return std::tie(first, second, third, fourth) 12 < std::tie(rhs.first, rhs.second, rhs.third, rhs.fourth); 13 } 14 inline bool operator>(const v& rhs) const { 15 return rhs.operator<(*this); 16 } 17 inline bool operator<=(const v& rhs) const { 18 return !rhs.operator<(*this); 19 } 20 inline bool operator>=(const v& rhs) const { 21 return !operator<(rhs); 22 } 23 24 // 等価比較演算子 25 inline bool operator==(const v& rhs) const { 26 return std::tie(first, second, third, fourth) 27 == std::tie(rhs.first, rhs.second, rhs.third, rhs.fourth); 28 } 29 inline bool operator!=(const v& rhs) const { 30 return !operator==(rhs); 31 } 32};

投稿2017/11/07 15:02

編集2017/11/07 15:05
yohhoy

総合スコア6189

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

こんにちは。

比較演算子が記載される前に、ちょっとやってみました。問題ないようです。
下記のフリー関数の代わりにメンバ関数を定義するとコンパイルエラーになりますので、メンバ関数のoperator< は使われないようです。(std::lessの実装がそういうものなのかも。)
つまり、お使いの環境でフリー関数としてのbool operator<(v const&, v const&)が定義されているのかも知れません。
Compairにメンバ関数のoperator<を使う比較関数を明示的に指定すれば意図通りに動作するかもです。

C++

1#include <iostream> 2#include <map> 3#include <string> 4 5struct v 6{ 7 std::string x; 8 v(std::string const& str) : x(str) { } 9 friend bool operator<(v const& iLhs, v const& iRhs) 10 { 11 return iLhs.x < iRhs.x; 12 } 13 bool operator==(v const& iRhs) 14 { 15 return x == iRhs.x; 16 } 17}; 18 19int main() 20{ 21 std::multimap<struct v, struct v> nmap = 22 { 23 {v("a"), v("1")}, 24 {v("b"), v("2")}, 25 {v("b"), v("3")}, 26 {v("b"), v("4")}, 27 {v("c"), v("5")}, 28 }; 29 30 v tmp_v("b"); 31 v tmp_v_value("3"); 32 33 std::cout << "----------\n"; 34 for (auto elm : nmap) 35 { 36 std::cout << elm.first.x << ", " << elm.second.x << "\n"; 37 } 38 //nmapからtmp_v, tmp_v_valueのペアを持つデータのみを削除するプログラムが以下.... 39 auto range = nmap.equal_range(tmp_v); //tmp_vはstruct v の変数 40 for (auto it = range.first; it != range.second; ++it) { 41 if(it->second == tmp_v_value) 42 { 43 nmap.erase(it); //tmp_v_value (tmp_v_valueはstruct vの変数)と一致したらそのイテレータを削除 44 break; 45 } 46 } 47 48 std::cout << "----------\n"; 49 for (auto elm : nmap) 50 { 51 std::cout << elm.first.x << ", " << elm.second.x << "\n"; 52 } 53}

結果:

---------- a, 1 b, 2 b, 3 b, 4 c, 5 ---------- a, 1 b, 2 b, 4 c, 5

wandbox

投稿2017/11/07 14:59

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問