How can I make an unordered set of pairs of integers in C++?

前端 未结 8 1460
陌清茗
陌清茗 2020-12-08 00:16

The following program does not compile an unordered set of pairs of integers, but it does for integers. Can unordered_set and its member functions be used on us

8条回答
  •  遥遥无期
    2020-12-08 00:33

    The other answers here all suggest building a hash function that somehow combines your two integers.

    This will work, but produces non-unique hashes. Though this is fine for your use of unordered_set, for some applications it may be unacceptable. In your case, if you happen to choose a bad hash function, it may lead to many unnecessary collisions.

    But you can produce unique hashes!

    int is usually 4 bytes. You could make this explicit by using int32_t.

    The hash's datatype is std::size_t. On most machines, this is 8 bytes. You can check this upon compilation.

    Since a pair consists of two int32_t types, you can put both numbers into an std::size_t to make a unique hash.

    That looks like this (I can't recall offhandedly how to force the compiler to treat a signed value as though it were unsigned for bit-manipulation, so I've written the following for uint32_t.):

    #include 
    #include 
    #include 
    #include 
    
    
    struct IntPairHash {
      std::size_t operator()(const std::pair &p) const {
        assert(sizeof(std::size_t)>=8);  //Ensure that std::size_t, the type of the hash, is large enough
        //Shift first integer over to make room for the second integer. The two are
        //then packed side by side.
        return (((uint64_t)p.first)<<32) | ((uint64_t)p.second);
      }
    };
    
    int main(){
      std::unordered_set< std::pair, IntPairHash> uset;
      uset.emplace(10,20);
      uset.emplace(20,30);
      uset.emplace(10,20);
      assert(uset.size()==2);
    }
    

提交回复
热议问题