summaryrefslogtreecommitdiffstats
path: root/gfx/gl/AutoMappable.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/gl/AutoMappable.h')
-rw-r--r--gfx/gl/AutoMappable.h139
1 files changed, 38 insertions, 101 deletions
diff --git a/gfx/gl/AutoMappable.h b/gfx/gl/AutoMappable.h
index f93b2ccb57..700e45d680 100644
--- a/gfx/gl/AutoMappable.h
+++ b/gfx/gl/AutoMappable.h
@@ -8,38 +8,13 @@
// Here be dragons.
#include <functional>
+#include <tuple>
-namespace mozilla::gfx {
+namespace mozilla {
template <class T>
-size_t Hash(const T&);
-
-template <class T>
-struct StaticStdHasher {
- static auto HashImpl(const T& v) { return std::hash<T>()(v); }
-};
-
-template <class T>
-struct StaticHasher {
- static auto HashImpl(const T& v) { return v.hash(); }
-};
-template <class T>
-struct StaticHasher<std::optional<T>> {
- static size_t HashImpl(const std::optional<T>& v) {
- if (!v) return 0;
- return Hash(*v);
- }
-};
-template <>
-struct StaticHasher<int> : public StaticStdHasher<int> {};
-template <>
-struct StaticHasher<bool> : public StaticStdHasher<bool> {};
-template <>
-struct StaticHasher<float> : public StaticStdHasher<float> {};
-
-template <class T>
-size_t Hash(const T& v) {
- return StaticHasher<T>::HashImpl(v);
+size_t StdHash(const T& t) {
+ return std::hash<T>()(t);
}
//-
@@ -52,97 +27,59 @@ inline size_t HashCombine(size_t seed, const size_t hash) {
}
// -
-// See
-// https://codereview.stackexchange.com/questions/136770/hashing-a-tuple-in-c17
+namespace detail {
template <class... Args, size_t... Ids>
-size_t HashTupleN(const std::tuple<Args...>& tup,
- const std::index_sequence<Ids...>&) {
+size_t StdHashTupleN(const std::tuple<Args...>& tup,
+ const std::index_sequence<Ids...>&) {
size_t seed = 0;
- for (const auto& hash : {Hash(std::get<Ids>(tup))...}) {
+ for (const auto& hash : {StdHash(std::get<Ids>(tup))...}) {
seed = HashCombine(seed, hash);
}
return seed;
}
-
-template <class... Args>
-size_t HashTuple(const std::tuple<Args...>& tup) {
- return HashTupleN(tup, std::make_index_sequence<sizeof...(Args)>());
-}
+} // namespace detail
// -
template <class T>
-auto MembersEq(const T& a, const T& b) {
- const auto atup = a.Members();
- const auto btup = b.Members();
- return atup == btup;
-}
+struct StdHashMembers {
+ size_t operator()(const T& t) const {
+ const auto members = t.Members();
+ return StdHash(members);
+ }
+};
-template <class T>
-auto MembersLt(const T& a, const T& b) {
- const auto atup = a.Members();
- const auto btup = b.Members();
- return atup == btup;
-}
+// -
-template <class T>
-auto MembersHash(const T& a) {
- const auto atup = a.Members();
- return HashTuple(atup);
-}
+#define MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(OP, T) \
+ bool operator OP(const T& rhs) const { return Members() OP rhs.Members(); }
-template <class T>
-struct MembersHasher final {
- auto operator()(const T& v) const { return v.hash(); }
-};
+#define MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(T) \
+ MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(==, T) \
+ MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(!=, T) \
+ MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(<, T) \
+ MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(<=, T) \
+ MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(>, T) \
+ MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(>=, T)
-/** E.g.:
-struct Foo {
- int i;
- bool b;
+template <class T>
+struct DeriveCmpOpMembers {
+ private:
+ auto Members() const { return reinterpret_cast<const T*>(this)->Members(); }
- auto Members() const { return std::tie(i, b); }
- INLINE_AUTO_MAPPABLE(Foo)
+ public:
+ MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(T)
};
-std::unordered_set<T, T::Hasher> easy;
-**/
-#define INLINE_DERIVE_MEMBERS_EQ(T) \
- friend bool operator==(const T& a, const T& b) { \
- return mozilla::gfx::MembersEq(a, b); \
- } \
- friend bool operator!=(const T& a, const T& b) { return !operator==(a, b); }
-#define INLINE_AUTO_MAPPABLE(T) \
- friend bool operator<(const T& a, const T& b) { \
- return mozilla::gfx::MembersLt(a, b); \
- } \
- INLINE_DERIVE_MEMBERS_EQ(T) \
- size_t hash() const { \
- return mozilla::gfx::MembersHash(*reinterpret_cast<const T*>(this)); \
- } \
- using Hasher = mozilla::gfx::MembersHasher<T>;
-
-// -
-/** E.g.:
-```
-struct Foo : public AutoMappable<Foo> {
- int i;
- bool b;
+} // namespace mozilla
- auto Members() const { return std::tie(i, b); }
-};
-std::unordered_set<T, T::Hasher> easy;
-```
-`easy.insert({{}, 2, true});`
-The initial {} is needed for aggregate initialization of AutoMappable<Foo>.
-Use INLINE_AUTO_MAPPABLE if this is too annoying.
-**/
-template <class T>
-struct AutoMappable {
- INLINE_AUTO_MAPPABLE(T)
+template <class... Args>
+struct std::hash<std::tuple<Args...>> {
+ size_t operator()(const std::tuple<Args...>& t) const {
+ return mozilla::detail::StdHashTupleN(
+ t, std::make_index_sequence<sizeof...(Args)>());
+ }
};
-} // namespace mozilla::gfx
-
#endif // MOZILLA_AUTO_MAPPABLE_H