c ++ unordered_map custom key

Add the C ++ 11 comprises a container class hashed unordered_set, unordered_map, unordered_multiset, unordered_multimap, i.e. before the familiar hash_set, hash_map like.

Such containers to the underlying implementation of the hash table, introduced by the use of such unordered_map container.

unordered_map is a template class, we need to provide five Rubik's Magic parameters. As follows: the type of key value, the value of the type of value, hash functions, functions equivalent, the container dispenser. The last three of which have default parameters, then we are not only required to provide the first two template parameters you can use it? Not necessarily. When we use when the built-key type (e.g., int, double, float, string, etc.), behind which there are three parameters default template specializations within the STL , it can be used directly. But once your class as a custom type, which have equal hash and provide your own. In fact, not difficult to understand, assuming your target is a stone, how the stones were hash, how the stone size than how it? The compiler does not know, of course, so you need to tell the compiler. Let these two cases illustrate, respectively.

(A), when the key is built-in types:

unordered_map <string, int> m_map; 

when the key type of built-in types, need only provide the value of the key can use. Where hash <string> and equal <int> are specialized version, the distributor of the entire container memory management, these three parameters are the default parameters.

(B), when the key for the custom type:

  For example, we simply define a package type, which is just a name, phone 2 data.

class package
{
public:
    string getName() const { return name; }
    long long getPhone() const { return phone; }

    package(string m_name = 0, long long m_pNum = 0);

    bool operator== (const package& p) const
    {    return name == p.name &&
               phone == p.phone; 
    }

private:
    string name;        
    long long phone;        
};

The native hash then the next package to use:

namespace std
{
    template<>
    struct hash<package>
    {
        size_t operator() (const package& s) const noexcept
        {
            return  hash<decltype(s.getName())>()(s.getName()) +
                    hash<decltype(s.getPhone())>()(s.getPhone());
        }
    }; // 间接调用原生Hash.
}

Or you can make use of the aid boost library hash_value:

namespace std
 {
     template<>
     struct hash<package>
     {
         size_t operator() (const package& s) const noexcept
         {
             auto t = make_tuple(s.getName(), s.getPhone());                                            
             size_t value = boost::hash_value(t);         
             return value;     // make_tuple(s.getName(), s.getPhone()) 等价于 tuple<string, long long>()(s.getName(), s.getPhone())
          }
     }; // 间接调用原生Hash.
  }

When the Hash function we (Japanese version of the package) and equivalent function (== operator overloading) provided, can use a customized version of the unordered_map:

unordered_map<package, int> m_map;

Test code is given below:

( Test environment: VS2017 )

#include <iostream>
#include <unordered_map>
#include <string>
#include <algorithm>
//#include <boost/functional/hash.hpp>   // 根据安装路径选择hash.hpp
#include <tuple>

using namespace std;


class package
{
public:
    string getName() const { return name; }
    long long getPhone() const { return phone; }

    package(string m_name = 0, long long m_pNum = 0);

    bool operator== (const package& p) const
    {    return name == p.name &&
               phone == p.phone; 
    }

private:
    string name;        
    long long phone;        
};

package::package(string m_name, long long m_pNum)
    : name(m_name), phone(m_pNum) { }

namespace std
{
    template<>
    struct hash<package>
    {
        size_t operator() (const package& s) const noexcept
        {
            return  hash<decltype(s.getName())>()(s.getName()) +
                    hash<decltype(s.getPhone())>()(s.getPhone());
            
            //auto t = make_tuple(s.getName(), s.getPhone());                                            
            //size_t value = boost::hash_value(t);         
            //return value;     // make_tuple(s.getName(), s.getPhone()) 等价于 tuple<string, long long>()(s.getName(), s.getPhone())
        }
    }; // 间接调用原生Hash.
}

int main()
{
    unordered_map<package, int> m_map;

    package p1{ "Wang", 13399996666};
    package p2{ "Li", 13399993333};
    package p3{ "Zhang", 13399992222};
    package p4{ "Zhou", 13399991111 };
    package p5{ "Wang", 13399996666};
    package p6{ "

    << m_map.bucket(p5) << " ";
    cout << m_map.bucket(p6) << " " << endl;

    return 0;
}

This switched: https: //www.cnblogs.com/xiguas/p/9977933.html

Guess you like

Origin www.cnblogs.com/Malphite/p/11568661.html