title: Why does case insensitive work with std::hash function for std::unordered_set?
body: <p>the question I have is not about using a case-insensitive std::unordered_set, but rather how does it work?</p>
  
  <pre><code>#include "stdafx.h"
  #include &lt;string&gt;
  #include &lt;iostream&gt;
  #include &lt;unordered_set&gt;
  #include "boost/algorithm/string.hpp"
  
  
  struct case_insensitive_comparer
  {
      bool operator () (const std::string&amp; x, const std::string&amp; y) const
      {
          return boost::iequals(x, y);
      }
  };
  
  using case_insensitive_set = std::unordered_set&lt;std::string, std::hash&lt;std::string&gt;, case_insensitive_comparer&gt;;
  
  std::vector&lt;std::string&gt; permute_case(const std::string&amp; s)
  {
      std::vector&lt;std::string&gt; strs;
  
      // Iterate through all bitmasks, 1 for uppercase, 0 for lowercase
      int msb = 1 &lt;&lt; (s.length() - 1);
      int upper = 1 &lt;&lt; s.length();
      std::locale loc;
      for (int i = 0; i &lt; upper; i++)
      {
          int bit = msb;
          std::string current = "";
          for (size_t j = 0; j &lt; s.length(); j++, bit &gt;&gt;= 1)
              current += (bit &amp; i) ? std::toupper(s[j], loc) : std::tolower(s[j], loc);
  
          strs.push_back(current);
      }
  
      return strs;
  }
  
  int main()
  {
      std::vector&lt;std::string&gt; strs = permute_case("awesome");
  
      case_insensitive_set set(strs.begin(), strs.end());
  
      // Check the hash
      for (auto&amp; s : strs)
          std::cout &lt;&lt; s &lt;&lt; " :" &lt;&lt; std::hash&lt;std::string&gt;()(s) &lt;&lt; "\n";
  
      // Check the element
      for (auto&amp; s : set)
          std::cout &lt;&lt; s &lt;&lt; "\n";
  
      return 0;
  }
  </code></pre>
  
  <p>So I use a string case-insensitive comparer for <code>std::unordered_set</code> and the <code>std::hash&lt;std::string&gt;</code> as the hash function. My basic understanding of hash set(I assume that unordered_set is like a hash set) is that it calculates the key's hash and puts it into the set if it doesn't exist yet. And the comparer Pred is for when the set is trying to insert a key and there is a hash collision, it has to decide if the keys are the same or different.</p>
  
  <p>Based on the code, it works regardless, so some of my assumptions are not correct. It would be helpful if someone tell me which of my assumptions are wrong.</p>
  
  <p>Thank you.</p>
  
  <p>Edit: My expectation for this case insensitive <code>unordered_set</code> is that there should only be 1 key inserted and it was the case that I observed, i.e only AWESOME is showed. So for my case I thought it worked but by the answer from kennytm really, I was just lucky getting all keys to be in the same bucket. I indeed use MSVC to compile the code. </p>