Remove redundant std::hash enum specializations (#42651)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/42651

Lots of boilerplate to define hash functions for different enums, so we can use them in `hash_combine`. This should not be needed, and seems like it might have been an artifact of older C++ version of standard library with bugs.

https://en.cppreference.com/w/cpp/utility/hash

> In addition to the above, the standard library provides specializations for all (scoped and unscoped) enumeration types. These may be (but are not required to be) implemented as std::hash<std::underlying_type<Enum>::type>.

Also moves `hash_combine` SFINAE to concepts for clarity and better error messages.

Changelog: [Internal]

Reviewed By: christophpurrer

Differential Revision: D53074535

fbshipit-source-id: 5fcb653dbe4aa51aa3d9d96f1511da3b7541270d
This commit is contained in:
Nick Gerleman
2024-01-29 17:39:49 -08:00
committed by Facebook GitHub Bot
parent 3a789a1776
commit 359738b6ca
4 changed files with 8 additions and 125 deletions
@@ -120,89 +120,3 @@ enum class HyphenationFrequency {
};
} // namespace facebook::react
namespace std {
template <>
struct hash<facebook::react::FontVariant> {
size_t operator()(const facebook::react::FontVariant& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::TextAlignment> {
size_t operator()(const facebook::react::TextAlignment& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::FontStyle> {
size_t operator()(const facebook::react::FontStyle& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::TextDecorationLineType> {
size_t operator()(const facebook::react::TextDecorationLineType& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::WritingDirection> {
size_t operator()(const facebook::react::WritingDirection& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::TextDecorationStyle> {
size_t operator()(const facebook::react::TextDecorationStyle& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::FontWeight> {
size_t operator()(const facebook::react::FontWeight& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::DynamicTypeRamp> {
size_t operator()(const facebook::react::DynamicTypeRamp& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::EllipsizeMode> {
size_t operator()(const facebook::react::EllipsizeMode& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::TextBreakStrategy> {
size_t operator()(const facebook::react::TextBreakStrategy& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::TextTransform> {
size_t operator()(const facebook::react::TextTransform& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::HyphenationFrequency> {
size_t operator()(const facebook::react::HyphenationFrequency& v) const {
return hash<int>()(static_cast<int>(v));
}
};
} // namespace std
@@ -248,19 +248,3 @@ enum class Role {
};
} // namespace facebook::react
namespace std {
template <>
struct hash<facebook::react::AccessibilityRole> {
size_t operator()(const facebook::react::AccessibilityRole& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::Role> {
size_t operator()(const facebook::react::Role& v) const {
return hash<int>()(static_cast<int>(v));
}
};
} // namespace std
@@ -38,20 +38,3 @@ enum class LayoutDirection {
};
} // namespace facebook::react
namespace std {
template <>
struct hash<facebook::react::LayoutDirection> {
size_t operator()(const facebook::react::LayoutDirection& v) const {
return hash<int>()(static_cast<int>(v));
}
};
template <>
struct hash<facebook::react::DisplayType> {
size_t operator()(const facebook::react::DisplayType& v) const {
return hash<int>()(static_cast<int>(v));
}
};
} // namespace std
@@ -8,20 +8,22 @@
#pragma once
#include <functional>
#include <type_traits>
namespace facebook::react {
template <
typename T,
typename... Rest,
bool Enabled = !std::is_same<T, const char*>::value,
typename = typename std::enable_if<Enabled>::type>
template <typename T>
concept Hashable = !std::is_same_v<T, const char*> && (requires(T a) {
{ std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
});
template <Hashable T, Hashable... Rest>
void hash_combine(std::size_t& seed, const T& v, const Rest&... rest) {
seed ^= std::hash<T>{}(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
(hash_combine(seed, rest), ...);
}
template <typename T, typename... Args>
template <Hashable T, Hashable... Args>
std::size_t hash_combine(const T& v, const Args&... args) {
std::size_t seed = 0;
hash_combine<T, Args...>(seed, v, args...);