title: Building an unordered map with tuples as keys
body: <p>In a C++ program with Boost, I am trying to build an unordered map whose keys are tuples of doubles: </p>
  
  <pre><code>typedef boost::tuples::tuple&lt;double, double, double, double&gt; Edge;
  typedef boost::unordered_map&lt; Edge, int &gt; EdgeMap;
  </code></pre>
  
  <p>Initializing the map completes OK, however, when I try to populate it with keys and values</p>
  
  <pre><code>EdgeMap map;
  Edge key (0.0, 0.1, 1.1, 1.1);
  map[key] = 1;
  </code></pre>
  
  <p>I encounter the following error message:</p>
  
  <pre><code>/usr/include/boost/functional/hash/extensions.hpp:176: error: no matching function for call to ‘hash_value(const boost::tuples::tuple&lt;double, double, double, double, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type&gt;&amp;)’
  </code></pre>
  
  <p>I presume this is because I need to specify a hash function for the tuple keys. How can I do that?</p>
  
  <p><strong>EDIT:</strong> </p>
  
  <p>Following the suggestions below, I wrote the following implementation:</p>
  
  <pre><code>#include &lt;boost/tuple/tuple.hpp&gt;
  #include &lt;boost/unordered_map.hpp&gt;
  
  typedef boost::tuples::tuple&lt;double, double, double, double&gt; Edge;
  
  struct ihash
      : std::unary_function&lt;Edge, std::size_t&gt;
  {
      std::size_t operator()(Edge const&amp; e) const
      {
          std::size_t seed = 0;
          boost::hash_combine( seed, e.get&lt;0&gt;() );
          boost::hash_combine( seed, e.get&lt;1&gt;() );
          boost::hash_combine( seed, e.get&lt;2&gt;() );
          boost::hash_combine( seed, e.get&lt;3&gt;() );
          return seed;
      }
  };
  
  struct iequal_to
      : std::binary_function&lt;Edge, Edge, bool&gt;
  {
      bool operator()(Edge const&amp; x, Edge const&amp; y) const
      {
          return ( x.get&lt;0&gt;()==y.get&lt;0&gt;() &amp;&amp;
                   x.get&lt;1&gt;()==y.get&lt;1&gt;() &amp;&amp;
                   x.get&lt;2&gt;()==y.get&lt;2&gt;() &amp;&amp;
                   x.get&lt;3&gt;()==y.get&lt;3&gt;());
      }
  };
  
  typedef boost::unordered_map&lt; Edge, int, ihash, iequal_to &gt; EdgeMap;
  
  int main() {
  
      EdgeMap map;
      Edge key (0.0, 0.1, 1.1, 1.1);
      map[key] = 1;
  
      return 0;
  }
  </code></pre>
  
  <p>Is it possible to shorten it?</p>