C++でユーザー定義クラス・構造体のunordered_setを作成する方法
このチュートリアルでは、C++においてユーザー定義のクラスや構造体を要素とする std::unordered_set を作成する方法について解説します。
通常の int や string などの基本型であれば、標準ライブラリがハッシュ関数を提供しているため、そのまま unordered_set を利用できます。しかし、独自に定義した構造体やクラスにはデフォルトのハッシュ関数が存在しないため、等価比較用の演算子(operator==)とカスタムハッシュ関数を自分で実装する必要があります。
実装の手順
具体的には以下の2つを準備します。
- operator== のオーバーロード: 要素同士が同一かどうかを判定するために必須です。constメンバ関数として定義します。
- ハッシュ関数クラス(ファンクタ):
operator()をオーバーロードし、オブジェクトからsize_t型のハッシュ値を返すようにします。
サンプルコード
#include <bits/stdc++.h>
using namespace std;
// ユーザー定義の構造体
struct Test {
int id;
// 等価比較演算子のオーバーロード
bool operator==(const Test& t) const {
return (this->id == t.id);
}
};
// ハッシュ関数を提供するクラス
class MyHashFunction {
public:
size_t operator()(const Test& t) const {
return t.id; // idをハッシュ値として使用
}
};
int main() {
Test t1 = { 110 }, t2 = { 102 }, t3 = { 101 }, t4 = { 115 };
// カスタムハッシュ関数を指定してunordered_setを定義
unordered_set<Test, MyHashFunction> us;
us.insert(t1);
us.insert(t2);
us.insert(t3);
us.insert(t4);
for (auto e : us) {
cout << e.id << " ";
}
return 0;
}実行結果
115 101 110 102
コードのポイント解説
unordered_set<Test, MyHashFunction>のように、第2テンプレート引数にカスタムハッシュ関数を渡すのがポイントです。operator==を定義しない場合、要素の重複チェックができずコンパイルエラーになります。- ハッシュ値は
size_t型で返す必要があります。ここでは単純にidの値をそのまま使っていますが、複数のメンバ変数を持つ場合は、各値を組み合わせた計算(例:XORや乗算の組み合わせ)を行うことで衝突を減らせます。
代替手段:std::hashの特殊化
カスタムハッシュクラスを作る代わりに、std::hash<Test> を特殊化して標準のハッシュとして登録する方法もあります。この場合は unordered_set<Test> と書くだけで済むようになります。用途に応じて使い分けると良いでしょう。
-
C++における構造体(struct)とクラス(class)の違いを徹底解説
C++において、構造体(struct)とクラス(class)は本質的にはほぼ同じものです。どちらもメンバ変数やメンバ関数を持つことができ、継承やコンストラクタなども利用できます。しかし、両者にはいくつかの重要な違いが存在します。この記事では、その主な違いについて具体例を交えて解説します。 違い1:デフォルトのアクセス指定子 最も大きな違いは、メンバのデフォルトのアクセスレベルです。 クラス:メンバはデフォルトで private(非公開)になります。 構造体:メンバはデフォルトで public(公開)になります。 実際にコードを見て、この違いを確認してみましょう。 クラスの場合(コンパイルエ
-
C++とOpenCVでバイナリ画像(二値画像)を作成する方法を解説
バイナリ画像(二値画像)とは、黒と白の2色のみで表現されるデジタル画像のことです。画像処理の観点から見ると、バイナリ画像は「0」と「1」という2つの値しか持たないピクセルで構成されています。ピクセルの値が0の場合は純粋な黒を、値が1の場合は純粋な白を表します。グレースケール画像では、各ピクセルが256段階の異なる値を持つのに対し、バイナリ画像では2つの値しか存在しません。このシンプルさゆえに、バイナリ画像はさまざまな用途で活用されています。例えば、モルフォロジー変換(形態学的処理)ではバイナリ画像が必要であり、背景から物体の形状を抽出する処理にもバイナリ画像が用いられます。OpenCVを使用す