AutoMappable.h (2137B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef MOZILLA_AUTO_MAPPABLE_H 6 #define MOZILLA_AUTO_MAPPABLE_H 7 8 // Here be dragons. 9 10 #include <functional> 11 #include <tuple> 12 13 namespace mozilla { 14 15 template <class T> 16 size_t StdHash(const T& t) { 17 return std::hash<T>()(t); 18 } 19 20 //- 21 // From Boost: 22 // https://www.boost.org/doc/libs/1_37_0/doc/html/hash/reference.html#boost.hash_combine 23 24 inline size_t HashCombine(size_t seed, const size_t hash) { 25 seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2); 26 return seed; 27 } 28 29 // - 30 31 namespace detail { 32 template <class... Args, size_t... Ids> 33 size_t StdHashTupleN(const std::tuple<Args...>& tup, 34 const std::index_sequence<Ids...>&) { 35 size_t seed = 0; 36 for (const auto& hash : {StdHash(std::get<Ids>(tup))...}) { 37 seed = HashCombine(seed, hash); 38 } 39 return seed; 40 } 41 } // namespace detail 42 43 // - 44 45 template <class T> 46 struct StdHashMembers { 47 size_t operator()(const T& t) const { 48 const auto members = t.Members(); 49 return StdHash(members); 50 } 51 }; 52 53 // - 54 55 #define MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(OP, T) \ 56 bool operator OP(const T& rhs) const { return Members() OP rhs.Members(); } 57 58 #define MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(T) \ 59 MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(==, T) \ 60 MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(!=, T) \ 61 MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(<, T) \ 62 MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(<=, T) \ 63 MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(>, T) \ 64 MOZ_MIXIN_DERIVE_CMP_OP_BY_MEMBERS(>=, T) 65 66 template <class T> 67 struct DeriveCmpOpMembers { 68 private: 69 auto Members() const { return reinterpret_cast<const T*>(this)->Members(); } 70 71 public: 72 MOZ_MIXIN_DERIVE_CMP_OPS_BY_MEMBERS(T) 73 }; 74 75 } // namespace mozilla 76 77 template <class... Args> 78 struct std::hash<std::tuple<Args...>> { 79 size_t operator()(const std::tuple<Args...>& t) const { 80 return mozilla::detail::StdHashTupleN( 81 t, std::make_index_sequence<sizeof...(Args)>()); 82 } 83 }; 84 85 #endif // MOZILLA_AUTO_MAPPABLE_H