index_base.h 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  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. namespace Carbon {
  10. template <typename DataType>
  11. class DataIterator;
  12. // A lightweight handle to an item identified by an opaque ID.
  13. //
  14. // This class is intended to be derived from by classes representing a specific
  15. // kind of ID, whose meaning as an integer is an implementation detail of the
  16. // type that vends the IDs. Typically this will be a vector index.
  17. //
  18. // Classes derived from IdBase are designed to be passed by value, not
  19. // reference or pointer. They are also designed to be small and efficient to
  20. // store in data structures.
  21. struct IdBase : public Printable<IdBase> {
  22. static constexpr int32_t InvalidIndex = -1;
  23. IdBase() = delete;
  24. constexpr explicit IdBase(int index) : index(index) {}
  25. auto Print(llvm::raw_ostream& output) const -> void {
  26. if (is_valid()) {
  27. output << index;
  28. } else {
  29. output << "<invalid>";
  30. }
  31. }
  32. constexpr auto is_valid() const -> bool { return index != InvalidIndex; }
  33. int32_t index;
  34. };
  35. // A lightweight handle to an item that behaves like an index.
  36. //
  37. // Unlike IdBase, classes derived from IndexBase are not completely opaque, and
  38. // provide at least an ordering between indexes that has meaning to an API
  39. // user. Additional semantics may be specified by the derived class.
  40. struct IndexBase : public IdBase {
  41. using IdBase::IdBase;
  42. };
  43. // Support equality comparison when one operand is a child of `IdBase`
  44. // (including `IndexBase`) and the other operand is either the same type or
  45. // convertible to that type.
  46. template <typename IndexType>
  47. requires std::derived_from<IndexType, IdBase>
  48. constexpr auto operator==(IndexType lhs, IndexType rhs) -> bool {
  49. return lhs.index == rhs.index;
  50. }
  51. template <typename IndexType, typename RHSType>
  52. requires std::derived_from<IndexType, IdBase> &&
  53. std::convertible_to<RHSType, IndexType>
  54. auto operator==(IndexType lhs, RHSType rhs) -> bool {
  55. return lhs.index == IndexType(rhs).index;
  56. }
  57. // Relational comparisons are only supported for types derived from `IndexBase`.
  58. template <typename IndexType>
  59. requires std::derived_from<IndexType, IndexBase>
  60. auto operator<=>(IndexType lhs, IndexType rhs) -> std::strong_ordering {
  61. return lhs.index <=> rhs.index;
  62. }
  63. } // namespace Carbon
  64. #endif // CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_