Developer's Blog

[VC++] std::unordered_map のキーに CAtlString を使うには

ハワイ山脈

こんにちは! フェンリル社内で Microsoft のライセンスに一番詳しい(かもしれない)RAPT こと山口です。

花粉症のメインシーズンがようやく終わったかと思ったら黄砂で結局マスクが手放せなくて、通勤途上はマスク+サングラスといった不審者風体を絶賛継続中な今日この頃、みなさまいかがお過ごしでしょうか。

信頼性の上がった Sleipnir 3.0.17 と、Sleipnir 3 の開発中に得た技術をフィードバックした 2.9.10 をリリースできてちょっと達成感に浸っていたら世間はもうゴールデンウィークに突入ですね。 みなさんはもう予定を立てているでしょうか、私はじっくり引き籠って溜まっている未読本でも読もうかと画策しているところです。

さて、今回はリッチでパワフルな Sleipnir 3 for Windows の開発環境である Visual C++ 2010 に関するネタとして、std::unordered_map のキーに CAtlString を使うためのおまじないについて書いてみようかと思います。

ハッシュ関数さえあれば!

通常であれば、std::unordered_map< CAtlString, int > とかするとコンパイルエラーになります。

なぜかというと、std::unordered_map は、キーとして指定された値のハッシュ値を検索用のキーとして使用しているのですが、CAtlString 用のハッシュ関数がデフォルトでは用意されていないからです。 そのため、std::unordered_map< std::wstring > はコンパイルできるのに、std::unordered_map< CAtlString > はコンパイルが通りません。

では、どうすればいいかというと、CAtlString 用のハッシュ関数を用意すれば良いのです。 ハッシュ関数はどんなのでも良いと思いますが、一番楽なのは、std::wstring 用のハッシュ関数にちょっと手を加えたものを作成するのが近道かと思います。

 // unordered_map のキーに CAtlString を使えるようにするためのハッシュ関数 template<> class std::hash< CAtlString > : public unary_function< CAtlString, size_t > { // hash functor public: typedef CAtlString _Kty; size_t operator()(const _Kty& _Keyval) const { // hash _Keyval to size_t value by pseudorandomizing transform size_t _Val = 2166136261U; size_t _First = 0; size_t _Last = _Keyval.GetLength(); size_t _Stride = 1 + _Last / 10; for(; _First < _Last; _First += _Stride) _Val = 16777619U * _Val ^ (size_t)_Keyval[_First]; return (_Val); } }; 

これだけ!

上記を共通ヘッダなどに記載しておけば、どこでも std::unordered_map< CString, std::tuple< CString, int, int > > などといった場合でも使用できるので便利かと思います。

それでは Enjoy Comfortable C++ Life!

ソーシャルアカウント

フェンリルのオフィシャル Twitter アカウントでは、フェンリルプロダクトの最新情報などをつぶやいています。よろしければフォローしてください!

Copyright © 2019 Fenrir Inc. All rights reserved.