{"id":22,"date":"2014-04-14T05:12:00","date_gmt":"2014-04-14T05:12:00","guid":{"rendered":"http:\/\/dev.fruitbyte.com\/?p=22"},"modified":"2015-07-13T22:23:55","modified_gmt":"2015-07-13T22:23:55","slug":"c-stl-containers-with-custom-hash-function","status":"publish","type":"post","link":"http:\/\/dev.fruitbyte.com\/?p=22","title":{"rendered":"C++ STL containers with custom hash function"},"content":{"rendered":"<p>That&#8217;s a bit unusual trip to side roads for me. I&#8217;ve been working with C++ for many years and considered myself pretty experienced with STL containers. I remembered (I thought) how to extend a class so. C++ is a language that does not forgive hiatuses. My approach to custom hash function was similar to what highest ranking answer in this stackoverflow answer is showing:<\/p>\n<p>http:\/\/stackoverflow.com\/questions\/647967\/how-to-extend-stdtr1hash-for-custom-types<\/p>\n<p>First of all, it&#8217;s a bit outdated, because with introduction of C++11 tr1 namespace became obsolete. Secondly, to my shame, I was unable to make my example compile. So after some head scratching, I decided to go for even simpler solution. It may be not as beautiful as what you can find in C++ books, but it works. So here it is.<\/p>\n<p>Our sample class looks like this:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">struct Square\r\n{\r\nunsigned long long x;\r\nunsigned long long y;\r\n\r\nSquare(unsigned long long _x, unsigned long long _y) : x(_x), y(_y) {};\r\n};\r\n<\/pre>\n<p>To make class work with STL containers like map and set you need to implement a method returning a hash value of the object.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">struct SquareHash\r\n{\r\nsize_t operator() (const Square&amp;amp; square) const\r\n{\r\nreturn square.y * 1000 + square.y;\r\n}\r\n};\r\n<\/pre>\n<p>Besides that you either need to implement a function that compares two values. In case of regular std::map or std::set it should be &#8220;&lt;&#8221; and in case of unordered_map and unordered_set &#8211; &#8220;==&#8221;. You can do it by implementing an operator&lt; or operator== for operands of your custom class, but I found it even clearer syntactically to implement a class:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">struct SquareEqual\r\n{\r\nbool operator() (const Square&amp;amp; lhs, const Square&amp;amp; rhs) const\r\n{\r\nreturn (lhs.x == rhs.x) &amp;amp;&amp;amp; (lhs.y == rhs.y);\r\n}\r\n};<\/pre>\n<p>Just in case, look at unordered_map declaration:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">template &lt; class Key, \/\/ unordered_map::key_type\r\nclass T, \/\/ unordered_map::mapped_type\r\nclass Hash = hash, \/\/ unordered_map::hasher\r\nclass Pred = equal_to, \/\/ unordered_map::key_equal\r\nclass Alloc = allocator &lt; pair&lt;const Key,T&gt; &gt;\/\/ unordered_map::allocator_type\r\nclass unordered_map;<\/pre>\n<p>That&#8217;s it! Now you can declare an unordered_map:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">unordered_set &lt;Square, SquareHash, SquareEqual&gt; visitedSquares;<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>That&#8217;s a bit unusual trip to side roads for me. I&#8217;ve been working with C++ for many years and considered myself pretty experienced with STL containers. I remembered (I thought) how to extend a class so. C++ is a language &hellip; <a href=\"http:\/\/dev.fruitbyte.com\/?p=22\"><em>Continue&nbsp;reading&nbsp;<span class=\"meta-nav\">&rarr;<\/span><\/em><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18],"tags":[46,19,20],"class_list":["post-22","post","type-post","status-publish","format-standard","hentry","category-c","tag-c","tag-recipe","tag-stl"],"_links":{"self":[{"href":"http:\/\/dev.fruitbyte.com\/index.php?rest_route=\/wp\/v2\/posts\/22","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/dev.fruitbyte.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/dev.fruitbyte.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/dev.fruitbyte.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/dev.fruitbyte.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=22"}],"version-history":[{"count":6,"href":"http:\/\/dev.fruitbyte.com\/index.php?rest_route=\/wp\/v2\/posts\/22\/revisions"}],"predecessor-version":[{"id":54,"href":"http:\/\/dev.fruitbyte.com\/index.php?rest_route=\/wp\/v2\/posts\/22\/revisions\/54"}],"wp:attachment":[{"href":"http:\/\/dev.fruitbyte.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=22"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/dev.fruitbyte.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=22"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/dev.fruitbyte.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=22"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}