mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-28 13:00:09 +01:00
With the toolchain splitting namespaces, ostream.h's `operator<<` templates aren't reliably found with name lookup, likely due to the loss of associated namespaces (zygoloid commented on this at https://github.com/carbon-language/carbon-lang/pull/3161#discussion_r1307941999). This is especially a barrier to moving the lex files into `Carbon::Lex`; versus other parts of the toolchain, they contain more printable types which are used cross-namespace, including `Carbon::Testing`. As a consequence, I'm looking at migrating ostream.h to a more reliable approach that doesn't rely as much on everything being in the `Carbon` namespace.
84 lines
2.7 KiB
C++
84 lines
2.7 KiB
C++
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
|
// Exceptions. See /LICENSE for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
|
|
#ifndef CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_
|
|
#define CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_
|
|
|
|
#include <type_traits>
|
|
|
|
#include "common/ostream.h"
|
|
|
|
namespace Carbon {
|
|
|
|
template <typename DataType>
|
|
class DataIterator;
|
|
|
|
// A lightweight handle to an item in a vector.
|
|
//
|
|
// DataIndex is designed to be passed by value, not reference or pointer. They
|
|
// are also designed to be small and efficient to store in data structures.
|
|
struct IndexBase : public Printable<IndexBase> {
|
|
static constexpr int32_t InvalidIndex = -1;
|
|
|
|
IndexBase() = delete;
|
|
constexpr explicit IndexBase(int index) : index(index) {}
|
|
|
|
auto Print(llvm::raw_ostream& output) const -> void {
|
|
if (is_valid()) {
|
|
output << index;
|
|
} else {
|
|
output << "<invalid>";
|
|
}
|
|
}
|
|
|
|
auto is_valid() const -> bool { return index != InvalidIndex; }
|
|
|
|
int32_t index;
|
|
};
|
|
|
|
// Like IndexBase, but also provides < and > comparison operators.
|
|
struct ComparableIndexBase : public IndexBase {
|
|
using IndexBase::IndexBase;
|
|
};
|
|
|
|
// Equality comparison for both IndexBase and ComparableIndexBase.
|
|
template <typename IndexType,
|
|
typename std::enable_if_t<std::is_base_of_v<IndexBase, IndexType>>* =
|
|
nullptr>
|
|
auto operator==(IndexType lhs, IndexType rhs) -> bool {
|
|
return lhs.index == rhs.index;
|
|
}
|
|
template <typename IndexType,
|
|
typename std::enable_if_t<std::is_base_of_v<IndexBase, IndexType>>* =
|
|
nullptr>
|
|
auto operator!=(IndexType lhs, IndexType rhs) -> bool {
|
|
return lhs.index != rhs.index;
|
|
}
|
|
|
|
// The < and > comparisons for only ComparableIndexBase.
|
|
template <typename IndexType, typename std::enable_if_t<std::is_base_of_v<
|
|
ComparableIndexBase, IndexType>>* = nullptr>
|
|
auto operator<(IndexType lhs, IndexType rhs) -> bool {
|
|
return lhs.index < rhs.index;
|
|
}
|
|
template <typename IndexType, typename std::enable_if_t<std::is_base_of_v<
|
|
ComparableIndexBase, IndexType>>* = nullptr>
|
|
auto operator<=(IndexType lhs, IndexType rhs) -> bool {
|
|
return lhs.index <= rhs.index;
|
|
}
|
|
template <typename IndexType, typename std::enable_if_t<std::is_base_of_v<
|
|
ComparableIndexBase, IndexType>>* = nullptr>
|
|
auto operator>(IndexType lhs, IndexType rhs) -> bool {
|
|
return lhs.index > rhs.index;
|
|
}
|
|
template <typename IndexType, typename std::enable_if_t<std::is_base_of_v<
|
|
ComparableIndexBase, IndexType>>* = nullptr>
|
|
auto operator>=(IndexType lhs, IndexType rhs) -> bool {
|
|
return lhs.index >= rhs.index;
|
|
}
|
|
|
|
} // namespace Carbon
|
|
|
|
#endif // CARBON_TOOLCHAIN_BASE_INDEX_BASE_H_
|