IdWrapper.h 2.3 KB

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