13

I am trying to create an unordered set of pairs

So far I have :

typedef std::pair<int, int> Move;
typedef std::unordered_set<Move> Set;

And I will be creating a set of Moves in the future for now I just have:

Set* King::possibleMoves() 
{
  Set hello;    <-------- THINK ERROR OCCURS HERE
  return &hello;
}

But i keep getting these 3 errors:

`/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/type_traits:770:38: error: 
  implicit instantiation of undefined template 'std::__1::hash<std::__1::pair<int, int>
  >'
: public integral_constant<bool, __is_empty(_Tp)> {};
                                 ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/memory:1951:40: note: 
  in instantiation of template class
  'std::__1::is_empty<std::__1::hash<std::__1::pair<int, int> > >' requested here
                            bool = is_empty<_T2>::value
                                   ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/memory:1973:44: note: 
  in instantiation of default argument for '__libcpp_compressed_pair_switch<unsigned
  long, std::__1::hash<std::__1::pair<int, int> >, false, false>' required here
template <class _T1, class _T2, unsigned = __libcpp_compressed_pair_switch<_T1, _T2>::value>
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/memory:2357:15: note: 
  in instantiation of default argument for '__libcpp_compressed_pair_imp<unsigned long,
  std::__1::hash<std::__1::pair<int, int> > >' required here
: private __libcpp_compressed_pair_imp<_T1, _T2>
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/__hash_table:527:55: note: 
  in instantiation of template class 'std::__1::__compressed_pair<unsigned long,
  std::__1::hash<std::__1::pair<int, int> > >' requested here
__compressed_pair<size_type, hasher>              __p2_;
                                                  ^
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/unordered_set:330:13: note: 
  in instantiation of template class 'std::__1::__hash_table<std::__1::pair<int, int>,
  std::__1::hash<std::__1::pair<int, int> >, std::__1::equal_to<std::__1::pair<int, int>
  >, std::__1::allocator<std::__1::pair<int, int> > >' requested here
__table __table_;
        ^
King.cpp:9:7: note: in instantiation of template class
  'std::__1::unordered_set<std::__1::pair<int, int>, std::__1::hash<std::__1::pair<int,
  int> >, std::__1::equal_to<std::__1::pair<int, int> >,
  std::__1::allocator<std::__1::pair<int, int> > >' requested here
 Set hello;
  ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/memory:3081:29: note: 
      template is declared here
template <class _Tp> struct hash;
                        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/memory:1951:55: error: 
  no member named 'value' in 'std::__1::is_empty<std::__1::hash<std::__1::pair<int, int>
  > >'
                            bool = is_empty<_T2>::value
                                   ~~~~~~~~~~~~~~~^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/memory:1973:44: note: 
  in instantiation of default argument for '__libcpp_compressed_pair_switch<unsigned
  long, std::__1::hash<std::__1::pair<int, int> >, false, false>' required here
template <class _T1, class _T2, unsigned = __libcpp_compressed_pair_switch<_T1, _T2>::value>
                                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The whole error is here (wouldnt let me paste above)

http://fixee.org/paste/528pvoq/

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
user3223763
  • 141
  • 1
  • 8
  • What OS and compiler version are you using? – Adrian Jan 22 '14 at 16:33
  • 7
    Unrelated to your problem but you are returning a pointer to a local variable. – Abhishek Bansal Jan 22 '14 at 16:34
  • MacOS mavericks and gcc. Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1 Apple LLVM version 5.0 (clang-500.2.79) (based on LLVM 3.3svn) Target: x86_64-apple-darwin13.0.0 Thread model: posix – user3223763 Jan 22 '14 at 16:34
  • Was just about to mention that. – Adrian Jan 22 '14 at 16:34
  • 2
    My guess it that there is no hash function defined for your pair. The issue of returning the address of a local variable will of course sting you later on. – CashCow Jan 22 '14 at 16:35
  • yeah the local variable was my bad but shall implement the hash actually will be creating a class as suggested below – user3223763 Jan 22 '14 at 16:38
  • 1
    I've updated your title to be clearer. Referring to the C++ language as "Cpp" is confusing; that abbreviation typically refers to the C preprocessor. I would have just changed "Cpp" to "C++", but that information is already in the tag. – Keith Thompson Jan 22 '14 at 16:40

1 Answers1

12

That error message appears when you have failed to specialise std::hash or provide a hasher type for your unordered container (see e.g. Using C++11 unordered_set in Visual C++ and clang). The XCode error in this case is particularly unfriendly!

C++11 does not provide a hash for pairs (or tuples), even of hashable types. This discussion indicates that this was primarily due to a lack of time to get anything better in; however I'm not aware whether there will be anything better in C++14.

Specialising std::hash<std::pair<int, int>> is probably not a good idea (and is not permitted by the language; specialising std templates is only allowed for user-defined types), so you'll have to provide a hasher:

struct MoveHasher {
    std::size_t operator()(const std::pair<int, int> &val) const { ... }
};
typedef std::unordered_set<Move, MoveHasher> Set;

See How do I combine hash values in C++0x? for how to write the hash function.

Alternatively, you could make Move a user-defined class (probably a good idea!) and then specialising std::hash will be fine.

Community
  • 1
  • 1
ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • I'd be tempted to write `struct PairHasher` which works for any pair transparently myself (calling `hash` for each half of the pair). While I was at it, make it `struct TupleHasher` that supports pairs and tuples. – Yakk - Adam Nevraumont Jan 22 '14 at 20:25