C++
C++でMapのキーとして、自分で定義した構造体を利用する
C++のstd::mapのキーに、自分で定義した構造体やクラスを使うことができます。ここでは、自分で定義した構造体を、std::mapのキーとして使う方法を紹介しています。
std::mapはデータを二分木で格納しているため、map内から指定されたファイルを探すことができるようにするために、キー同士を比較できる必要があります。
よって、自分で定義した構造体に、データだけでなく、比較演算子<を定義してあげる必要があります。
ここで紹介しているサンプルコードは、intとchar[100]を持った構造体をキーとしたい場合のサンプルです。
もちろん、比較演算子の処理の書き方は、ここで紹介している方法に限りません。
ただ一点注意しなければならないのが、比較演算子は適切に大小を比較できるように定義してあげなければいけません。
当たり前じゃないかと思われるかもしれませんが、筆者は一度、ここで落とし穴にはまってしまい、デバッグに時間がかかったことがあります。。
極端な話、intのキーに対して0だったらfalse、それ以外はtrueを返す、というような処理にしちゃうと、正しく比較できなくなり、正常に取り出すことはおろか、格納することすらできなくなってしまうと思います。
恐ろしいのは、コンパイルはそれでも通りますし、一つ目のデータは問題なく格納も取り出すこともできてしまうとこです。
自分で定義した構造体やクラスをmapのキーにして動作がおかしかったら、まずは比較演算子の処理の中身を疑ってみるといいかも知れません。
use_struct_as_key_of_map.cpp
#include<string.h>
#include<map>
#include<string>
#include<iostream>
/**
* @struct intStringKey_t
* @brief This strcut is int-string key for map
*/
struct intStringKey_t {
int intKey;
char stringKey[100];
bool operator < (const intStringKey_t& rhs) const {
if (intKey < rhs.intKey) {
return true;
}
if (intKey > rhs.intKey) {
return false;
}
if ((strcmp(stringKey, rhs.stringKey)) < 0) {
return true;
}
if ((strcmp(stringKey, rhs.stringKey)) > 0) {
return false;
}
return false;
}
}; // intStringKey_t
int main(void) {
// Create map
std::map<intStringKey_t, std::string> sampleMap;
// Create keys
intStringKey_t key1 = {1, "first"};
intStringKey_t key2 = {2, "second"};
intStringKey_t key3 = {3, "third"};
// Insert values with keys
sampleMap.insert(std::map<intStringKey_t, std::string>::value_type(key1, "1stValue"));
sampleMap.insert(std::map<intStringKey_t, std::string>::value_type(key2, "2ndValue"));
sampleMap.insert(std::map<intStringKey_t, std::string>::value_type(key3, "3rdValue"));
// Show all key and value
std::map<intStringKey_t, std::string>::iterator it = sampleMap.begin();
while(it != sampleMap.end()) {
std::cout
<< (*it).first.intKey
<< ", "
<< (*it).first.stringKey
<< ": "
<< (*it).second
<< std::endl;
++it;
}
return 0;
}
実行結果
$ g++ use_struct_as_key_of_map.cpp -o use_struct_as_key_of_map.cpp
$ ./use_struct_as_key_of_map
1, first: 1stValue
2, second: 2ndValue
3, third: 3rdValue