IdWrapper.h 2.3 KB

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