2015-07-03 7 views
5

Als Übung versuchte ich zu sehen, ob ich SFINAE verwenden könnte, um eine std::hash Spezialisierung für std::pair und std::tuple zu erstellen, wenn alle seine Template-Parameter von einem vorzeichenlosen Typ sind. Ich habe ein wenig Erfahrung mit ihnen, aber von dem, was ich verstehe, muss die Hash-Funktion bereits mit einem typename Enabled = void für mich Templated eine Spezialisierung hinzuzufügen. Ich bin mir nicht sicher, wohin ich von hier aus gehen soll. Hier ist ein Versuch, der nicht funktioniert.Std :: Hash-Spezialisierung mit SFINAE?

#include <functional> 
#include <type_traits> 
#include <unordered_set> 
#include <utility> 

namespace std { 
template <typename T, typename Enabled = void> 
struct hash<std::pair<T, T>, std::enable_if_t<std::is_unsigned<T>::value>> 
{ 
    size_t operator()(const std::pair<T, T>& x) const 
    { 
     return x; 
    } 
}; 
}; // namespace std 


int 
main(int argc, char ** argv) 
{ 
    std::unordered_set<std::pair<unsigned, unsigned>> test{}; 
    return 0; 
} 

Fehler:

hash_sfinae.cpp:7:42: error: default template argument in a class template partial specialization 
template <typename T, typename Enabled = void> 
          ^
hash_sfinae.cpp:8:8: error: too many template arguments for class template 'hash' 
struct hash<std::pair<T, T>, std::enable_if_t<std::is_unsigned<T>::value>> 

Es geht darum, was ich erwartet habe, weil ich versuche, die Template-Parameter zu erweitern, um hash ... Aber ich bin die Technik nicht sicher, ob diese Fälle zu behandeln, dann. Kann mir jemand helfen zu verstehen?

Antwort

9

Sie sollten nicht spezialisieren std::hash für Typen, die nicht von einem Typ abhängt, den Sie selbst definiert haben.

Das heißt, könnte dieser Hack funktioniert:

template<class T, class E> 
using first = T; 

template <typename T> 
struct hash<first<std::pair<T, T>, std::enable_if_t<std::is_unsigned<T>::value>>> 
{ 
    size_t operator()(const std::pair<T, T>& x) const 
    { 
     return x; 
    } 
}; 

Wirklich, obwohl dies nicht tun. Schreibe deinen eigenen Hasher.

+0

Es gibt einen guten Grund, 'std :: hash' für Paare/Tupel nicht zu spezialisieren: Ich würde wirklich erwarten, dass ein automatisch kombinierender Hash irgendwann in' std' erscheinen wird. – Yakk