Ich bin kein Profi in C++, aber irgendwie habe ich eine Lösung bei der Portierung meines MSVS 2015 C++ - Code auf MinGW 4.9.2 zur Verfügung gestellt, um std::hash
Klasse zu spezialisieren, um alle enum
s zu unterstützen. Es gibt irgendwelche C++ - Compiler-Entwickler oder C++ - Pro-Programmierer hier, können Sie erklären, warum diese Spezialisierung funktioniert, obwohl es Undefined Behavior nach dem C++ - Standard heißt?Warum bietet dieser Code Spezialisierung für ** ALL ** enums für std :: hash template?
Link for full code with samples on Gist
#include <unordered_set>
#include <functional>
#if (defined __GNUC__) && (__GNUC__ < 6)
// Adds support of std::hash<enum T> to libstdc++.
// GCC 6 provides it out of the box.
namespace std {
template<typename T>
struct hash {
constexpr size_t operator()(typename std::enable_if<std::is_enum<T>::value, T>::type s) const noexcept {
return static_cast<size_t>(s);
}
};
}
#endif
Unterstützung für die Bereitstellung von std::hash<enum T>
bedeutet, dass alle Klassen wie std::unordered_XXX
jede enum
als Schlüssel unterstützen.
GCC 6.1.0 mit diese std::hash
Definition mit Fehlern
error: redefinition of 'struct std::hash<_Tp>'
GCC 5.3.0 ohne diese std::hash
Definition nicht für std :: unordered_set mit folgendem Fehler fehl:
In file included from /usr/local/gcc-5.3.0/include/c++/5.3.0/bits/hashtable.h:35:0,
from /usr/local/gcc-5.3.0/include/c++/5.3.0/unordered_set:47,
from prog.cc:1:
/usr/local/gcc-5.3.0/include/c++/5.3.0/bits/hashtable_policy.h: In instantiation of 'struct std::__detail::__is_noexcept_hash<Foo, std::hash<Foo> >':
/usr/local/gcc-5.3.0/include/c++/5.3.0/type_traits:137:12: required from 'struct std::__and_<std::__is_fast_hash<std::hash<Foo> >, std::__detail::__is_noexcept_hash<Foo, std::hash<Foo> > >'
/usr/local/gcc-5.3.0/include/c++/5.3.0/type_traits:148:38: required from 'struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<Foo> >, std::__detail::__is_noexcept_hash<Foo, std::hash<Foo> > > >'
/usr/local/gcc-5.3.0/include/c++/5.3.0/bits/unordered_set.h:95:63: required from 'class std::unordered_set<Foo>'
prog.cc:25:25: required from here
/usr/local/gcc-5.3.0/include/c++/5.3.0/bits/hashtable_policy.h:85:34: error: no match for call to '(const std::hash<Foo>) (const Foo&)'
noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
^
In file included from /usr/local/gcc-5.3.0/include/c++/5.3.0/bits/move.h:57:0,
from /usr/local/gcc-5.3.0/include/c++/5.3.0/bits/stl_pair.h:59,
from /usr/local/gcc-5.3.0/include/c++/5.3.0/utility:70,
from /usr/local/gcc-5.3.0/include/c++/5.3.0/unordered_set:38,
from prog.cc:1:
/usr/local/gcc-5.3.0/include/c++/5.3.0/type_traits: In instantiation of 'struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<Foo> >, std::__detail::__is_noexcept_hash<Foo, std::hash<Foo> > > >':
/usr/local/gcc-5.3.0/include/c++/5.3.0/bits/unordered_set.h:95:63: required from 'class std::unordered_set<Foo>'
prog.cc:25:25: required from here
/usr/local/gcc-5.3.0/include/c++/5.3.0/type_traits:148:38: error: 'value' is not a member of 'std::__and_<std::__is_fast_hash<std::hash<Foo> >, std::__detail::__is_noexcept_hash<Foo, std::hash<Foo> > >'
: public integral_constant<bool, !_Pp::value>
...
Sieht so aus, als gäbe es nur Vorlage struct hash; in GCC <6.1.0. Ich meine, es gibt keinen Körper für diese Vorlage und das bedeutet, dass ich den Körper mit meinem Code versehe. Habe ich Recht? –
slavanap
@slav ja. Es ist immer noch ein schlecht geformtes Programm ohne Diagnose erforderlich, aber der Compiler erzeugt ein Programm ohne Fehlermeldung, und dieses Programm (dessen Verhalten nicht mehr durch den Standard geregelt wird) verhält sich aufgrund von, was Sie wollen Implementierungsquirken. Grundsätzlich lohnt es sich nicht, dies zu tun, wenn die Kosten, die eingespart werden, ein ", enum_hash" zu einer ungeordneten Map/Sets hinzufügen. – Yakk