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

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

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

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

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

Q&A

解決済

1回答

1035閲覧

unordered_mapでの独自クラスの使用について

mytest2

総合スコア10

C++11

C++11は2011年に容認されたC++のISO標準です。以前のC++03に代わるもので、中枢の言語の変更・修正、標準ライブラリの拡張・改善を加えたものです。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

C++

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

1グッド

0クリップ

投稿2017/07/05 10:35

編集2017/07/05 10:40

###前提・実現したいこと
C++のunordered_mapで、独自に作成したクラスを使いたいのですが、うまいhash化の仕方が分かりません。
調べてみて、プログラムを書いて動かしたのですが、見た目上は、うまく動いているように見えます…。ですが、心配なので、質問させていただきました。

###発生している問題・エラーメッセージ
一応、動きますが、プログラム的に問題がないものなのか分かりません。

###該当のソースコード

#include <iostream> #include <unordered_map> #include <vector> using namespace std; class A { public: A(vector<string> text, vector<int> num) { this->text = text; this->num = num; } vector<std::string> text; vector<int> num; }; bool operator==(const A &lhs, const A &rhs) { return lhs.text == rhs.text && lhs.num == rhs.num; } namespace std { template <> class hash<A> { public: size_t operator()(const A& x) const{ unsigned int s = 0; for (int i = 0; i < x.text.size(); i++) { s ^= hash<string>()(x.text[i]); } for (int i = 0; i < x.num.size(); i++) { s ^= hash<int>()(x.num[i]); } return s; } }; } int main() { A a = A({ "test","aa" }, {1,1}); A aa = A({ "test","aa" }, { 0,1 }); A b = A({ "test","aa" }, { 2,1 }); A c = A({ "test","aa" }, { 0,1 }); unordered_map<A,int> z; z[a] ++; z[aa] ++; z[b] ++; z[c] ++; for (auto itr = z.begin(); itr != z.end(); itr++) { for (int i = 0; i < itr->first.num.size(); i++) { cout << itr->first.num[i] << ","; } cout << " "; for (int i = 0; i < itr->first.text.size(); i++) { cout << itr->first.text[i].c_str() << ","; } cout << ":" << itr->second << endl; } }

###試したこと
いろいろ調べてみて、intなどをhashにする方法はわかりましたが、複数個あった場合がよく分かりません。

###補足情報(言語/FW/ツール等のバージョンなど)
C++11 , VisualStudio2017

yohhoy👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

複数のhashを1つのhashにする時,うまくやらないとhashの衝突が多発することがあります
Boostにはhash_combineという関数があり,これを使って複数のhashを1つのhashにするようです.ですのでこれを使うのがいいと思います
http://www.boost.org/doc/libs/1_55_0/doc/html/hash/combine.html

hash_combineの実装は次のようになっています

cpp

1template<typename T> void hash_combine(size_t & seed, T const& v) { 2 seed ^= hash_value(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 3}

よって以下のように実装するのはいかがでしょうか?

cpp

1template<typename T> void hash_combine(size_t & seed, T const& v) { 2 seed ^= hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2); 3} 4 5namespace std { 6 template <> 7 class hash<A> { 8 public: 9 size_t operator()(const A& x) const{ 10 size_t s = 0; 11 for (int i = 0; i < x.text.size(); i++) 12 { 13 hash_combine(s, x.text[i]); 14 } 15 for (int i = 0; i < x.num.size(); i++) 16 { 17 hash_combine(s, x.num[i]); 18 } 19 return s; 20 } 21 }; 22}

投稿2017/07/05 12:54

odan

総合スコア54

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

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

mytest2

2017/07/06 09:16

ありがとうございます。急いでいたので非常に助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問