xref: /aosp_15_r20/external/pytorch/c10/util/IdWrapper.h (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1 #pragma once
2 
3 #include <cstddef>
4 #include <functional>
5 #include <utility>
6 
7 namespace c10 {
8 
9 /**
10  * This template simplifies generation of simple classes that wrap an id
11  * in a typesafe way. Namely, you can use it to create a very lightweight
12  * type that only offers equality comparators and hashing. Example:
13  *
14  *   struct MyIdType final : IdWrapper<MyIdType, uint32_t> {
15  *     constexpr explicit MyIdType(uint32_t id): IdWrapper(id) {}
16  *   };
17  *
18  * Then in the global top level namespace:
19  *
20  *   C10_DEFINE_HASH_FOR_IDWRAPPER(MyIdType);
21  *
22  * That's it - equality operators and hash functions are automatically defined
23  * for you, given the underlying type supports it.
24  */
25 template <class ConcreteType, class UnderlyingType>
26 class IdWrapper {
27  public:
28   using underlying_type = UnderlyingType;
29   using concrete_type = ConcreteType;
30 
31  protected:
IdWrapper(underlying_type id)32   constexpr explicit IdWrapper(underlying_type id) noexcept(
33       noexcept(underlying_type(std::declval<underlying_type>())))
34       : id_(id) {}
35 
underlyingId()36   constexpr underlying_type underlyingId() const
37       noexcept(noexcept(underlying_type(std::declval<underlying_type>()))) {
38     return id_;
39   }
40 
41  private:
hash_value(const concrete_type & v)42   friend size_t hash_value(const concrete_type& v) {
43     return std::hash<underlying_type>()(v.id_);
44   }
45 
46   // TODO Making operator== noexcept if underlying type is noexcept equality
47   // comparable doesn't work with GCC 4.8.
48   //      Fix this once we don't need GCC 4.8 anymore.
49   friend constexpr bool operator==(
50       const concrete_type& lhs,
51       const concrete_type& rhs) noexcept {
52     return lhs.id_ == rhs.id_;
53   }
54 
55   // TODO Making operator!= noexcept if operator== is noexcept doesn't work with
56   // GCC 4.8.
57   //      Fix this once we don't need GCC 4.8 anymore.
58   friend constexpr bool operator!=(
59       const concrete_type& lhs,
60       const concrete_type& rhs) noexcept {
61     return !(lhs == rhs);
62   }
63 
64   underlying_type id_;
65 };
66 
67 } // namespace c10
68 
69 #define C10_DEFINE_HASH_FOR_IDWRAPPER(ClassName) \
70   namespace std {                                \
71   template <>                                    \
72   struct hash<ClassName> {                       \
73     size_t operator()(ClassName x) const {       \
74       return hash_value(x);                      \
75     }                                            \
76   };                                             \
77   }
78