index_base.h 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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 <iterator>
  9. #include <type_traits>
  10. #include "common/ostream.h"
  11. #include "llvm/ADT/iterator.h"
  12. namespace Carbon {
  13. template <typename DataType>
  14. class DataIterator;
  15. // A lightweight handle to an item identified by an opaque ID.
  16. //
  17. // This class is intended to be derived from by classes representing a specific
  18. // kind of ID, whose meaning as an integer is an implementation detail of the
  19. // type that vends the IDs. Typically this will be a vector index.
  20. //
  21. // Classes derived from IdBase are designed to be passed by value, not
  22. // reference or pointer. They are also designed to be small and efficient to
  23. // store in data structures.
  24. struct IdBase : public Printable<IdBase> {
  25. static constexpr int32_t InvalidIndex = -1;
  26. IdBase() = delete;
  27. constexpr explicit IdBase(int index) : index(index) {}
  28. auto Print(llvm::raw_ostream& output) const -> void {
  29. if (is_valid()) {
  30. output << index;
  31. } else {
  32. output << "<invalid>";
  33. }
  34. }
  35. constexpr auto is_valid() const -> bool { return index != InvalidIndex; }
  36. int32_t index;
  37. };
  38. // A lightweight handle to an item that behaves like an index.
  39. //
  40. // Unlike IdBase, classes derived from IndexBase are not completely opaque, and
  41. // provide at least an ordering between indexes that has meaning to an API
  42. // user. Additional semantics may be specified by the derived class.
  43. struct IndexBase : public IdBase {
  44. using IdBase::IdBase;
  45. };
  46. // Support equality comparison when one operand is a child of `IdBase`
  47. // (including `IndexBase`) and the other operand is either the same type or
  48. // convertible to that type.
  49. template <typename IndexType>
  50. requires std::derived_from<IndexType, IdBase>
  51. constexpr auto operator==(IndexType lhs, IndexType rhs) -> bool {
  52. return lhs.index == rhs.index;
  53. }
  54. template <typename IndexType, typename RHSType>
  55. requires std::derived_from<IndexType, IdBase> &&
  56. std::convertible_to<RHSType, IndexType>
  57. auto operator==(IndexType lhs, RHSType rhs) -> bool {
  58. return lhs.index == IndexType(rhs).index;
  59. }
  60. // Relational comparisons are only supported for types derived from `IndexBase`.
  61. template <typename IndexType>
  62. requires std::derived_from<IndexType, IndexBase>
  63. auto operator<=>(IndexType lhs, IndexType rhs) -> std::strong_ordering {
  64. return lhs.index <=> rhs.index;
  65. }
  66. // A random-access iterator for arrays using IndexBase-derived types.
  67. template <typename IndexT>
  68. class IndexIterator
  69. : public llvm::iterator_facade_base<IndexIterator<IndexT>,
  70. std::random_access_iterator_tag,
  71. const IndexT, int>,
  72. public Printable<IndexIterator<IndexT>> {
  73. public:
  74. IndexIterator() = delete;
  75. explicit IndexIterator(IndexT index) : index_(index) {}
  76. auto operator==(const IndexIterator& rhs) const -> bool {
  77. return index_ == rhs.index_;
  78. }
  79. auto operator<=>(const IndexIterator& rhs) const -> std::strong_ordering {
  80. return index_ <=> rhs.index_;
  81. }
  82. auto operator*() const -> const IndexT& { return index_; }
  83. using llvm::iterator_facade_base<IndexIterator,
  84. std::random_access_iterator_tag,
  85. const IndexT, int>::operator-;
  86. auto operator-(const IndexIterator& rhs) const -> int {
  87. return index_.index - rhs.index_.index;
  88. }
  89. auto operator+=(int n) -> IndexIterator& {
  90. index_.index += n;
  91. return *this;
  92. }
  93. auto operator-=(int n) -> IndexIterator& {
  94. index_.index -= n;
  95. return *this;
  96. }
  97. // Prints the raw token index.
  98. auto Print(llvm::raw_ostream& output) const -> void {
  99. output << index_.index;
  100. }
  101. private:
  102. IndexT index_;
  103. };
  104. } // namespace Carbon
  105. #endif // CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_