index_base.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_
  5. #define CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_
  6. #include <compare>
  7. #include <concepts>
  8. #include "common/ostream.h"
  9. #include "llvm/ADT/DenseMapInfo.h"
  10. namespace Carbon {
  11. template <typename DataType>
  12. class DataIterator;
  13. // A lightweight handle to an item identified by an opaque ID.
  14. //
  15. // This class is intended to be derived from by classes representing a specific
  16. // kind of ID, whose meaning as an integer is an implementation detail of the
  17. // type that vends the IDs. Typically this will be a vector index.
  18. //
  19. // Classes derived from IdBase are designed to be passed by value, not
  20. // reference or pointer. They are also designed to be small and efficient to
  21. // store in data structures.
  22. struct IdBase : public Printable<IdBase> {
  23. static constexpr int32_t InvalidIndex = -1;
  24. IdBase() = delete;
  25. constexpr explicit IdBase(int index) : index(index) {}
  26. auto Print(llvm::raw_ostream& output) const -> void {
  27. if (is_valid()) {
  28. output << index;
  29. } else {
  30. output << "<invalid>";
  31. }
  32. }
  33. constexpr auto is_valid() const -> bool { return index != InvalidIndex; }
  34. int32_t index;
  35. };
  36. // A lightweight handle to an item that behaves like an index.
  37. //
  38. // Unlike IdBase, classes derived from IndexBase are not completely opaque, and
  39. // provide at least an ordering between indexes that has meaning to an API
  40. // user. Additional semantics may be specified by the derived class.
  41. struct IndexBase : public IdBase {
  42. using IdBase::IdBase;
  43. };
  44. // Support equality comparison when one operand is a child of `IdBase`
  45. // (including `IndexBase`) and the other operand is either the same type or
  46. // convertible to that type.
  47. template <typename IndexType>
  48. requires std::derived_from<IndexType, IdBase>
  49. constexpr auto operator==(IndexType lhs, IndexType rhs) -> bool {
  50. return lhs.index == rhs.index;
  51. }
  52. template <typename IndexType, typename RHSType>
  53. requires std::derived_from<IndexType, IdBase> &&
  54. std::convertible_to<RHSType, IndexType>
  55. auto operator==(IndexType lhs, RHSType rhs) -> bool {
  56. return lhs.index == IndexType(rhs).index;
  57. }
  58. // Relational comparisons are only supported for types derived from `IndexBase`.
  59. template <typename IndexType>
  60. requires std::derived_from<IndexType, IndexBase>
  61. auto operator<=>(IndexType lhs, IndexType rhs) -> std::strong_ordering {
  62. return lhs.index <=> rhs.index;
  63. }
  64. // Provides base support for use of IdBase types as DenseMap/DenseSet keys.
  65. //
  66. // Usage (in global namespace):
  67. // template <>
  68. // struct llvm::DenseMapInfo<Carbon::MyType>
  69. // : public Carbon::IndexMapInfo<Carbon::MyType> {};
  70. template <typename Index>
  71. struct IndexMapInfo {
  72. static inline auto getEmptyKey() -> Index {
  73. return Index(llvm::DenseMapInfo<int32_t>::getEmptyKey());
  74. }
  75. static inline auto getTombstoneKey() -> Index {
  76. return Index(llvm::DenseMapInfo<int32_t>::getTombstoneKey());
  77. }
  78. static auto getHashValue(const Index& val) -> unsigned {
  79. return llvm::DenseMapInfo<int32_t>::getHashValue(val.index);
  80. }
  81. static auto isEqual(const Index& lhs, const Index& rhs) -> bool {
  82. return lhs == rhs;
  83. }
  84. };
  85. } // namespace Carbon
  86. #endif // CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_