From 237c42c78fce7909e548d0f5c1cce6e33ddde74e Mon Sep 17 00:00:00 2001 From: Laramie Leavitt Date: Wed, 7 Jan 2026 08:32:30 -0800 Subject: [PATCH] Convert FastTypeIdType from an alias to a struct. PiperOrigin-RevId: 853275176 Change-Id: I03979c49739d1664ede2fa9be1034ddeb379447d --- absl/base/fast_type_id.h | 32 ++++++++++++++++++++++++++++++-- absl/base/fast_type_id_test.cc | 3 +++ absl/flags/internal/flag.h | 6 +++--- 3 files changed, 36 insertions(+), 5 deletions(-) diff --git a/absl/base/fast_type_id.h b/absl/base/fast_type_id.h index ff250276..a1214da0 100644 --- a/absl/base/fast_type_id.h +++ b/absl/base/fast_type_id.h @@ -16,6 +16,8 @@ #ifndef ABSL_BASE_FAST_TYPE_ID_H_ #define ABSL_BASE_FAST_TYPE_ID_H_ +#include + #include "absl/base/config.h" namespace absl { @@ -29,14 +31,40 @@ struct FastTypeTag { } // namespace base_internal // The type returned by `absl::FastTypeId()`. -using FastTypeIdType = const void*; +class FastTypeIdType { + public: + // Creates a value that does not correspond to any type. This value is + // distinct from any value returned by `FastTypeId()`. + constexpr FastTypeIdType() = default; + + template + friend H AbslHashValue(H h, FastTypeIdType x) { + return H::combine(std::move(h), x.ptr_); + } + + friend constexpr bool operator==(FastTypeIdType a, FastTypeIdType b) { + return a.ptr_ == b.ptr_; + } + friend constexpr bool operator!=(FastTypeIdType a, FastTypeIdType b) { + return a.ptr_ != b.ptr_; + } + + private: + // `FastTypeId()` is the generator method for FastTypeIdType values. + template + friend constexpr FastTypeIdType FastTypeId(); + + explicit constexpr FastTypeIdType(const void* ptr) : ptr_(ptr) {} + + const void* ptr_ = nullptr; +}; // `absl::FastTypeId()` evaluates at compile-time to a unique id for the // passed-in type. These are meant to be good match for keys into maps or // straight up comparisons. template constexpr FastTypeIdType FastTypeId() { - return &base_internal::FastTypeTag::kDummyVar; + return FastTypeIdType(&base_internal::FastTypeTag::kDummyVar); } ABSL_NAMESPACE_END diff --git a/absl/base/fast_type_id_test.cc b/absl/base/fast_type_id_test.cc index 3068e4bb..d27d9fa4 100644 --- a/absl/base/fast_type_id_test.cc +++ b/absl/base/fast_type_id_test.cc @@ -24,6 +24,9 @@ namespace { +// Ensure that absl::bit_cast works between FastTypeIdType and void*. +static_assert(sizeof(absl::FastTypeIdType) == sizeof(void*)); + // NOLINTBEGIN(runtime/int) #define PRIM_TYPES(A) \ A(bool) \ diff --git a/absl/flags/internal/flag.h b/absl/flags/internal/flag.h index cab9d169..285d8424 100644 --- a/absl/flags/internal/flag.h +++ b/absl/flags/internal/flag.h @@ -135,7 +135,7 @@ inline size_t Sizeof(FlagOpFn op) { } // Returns fast type id corresponding to the value type. inline FlagFastTypeId FastTypeId(FlagOpFn op) { - return reinterpret_cast( + return absl::bit_cast( op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr)); } // Returns fast type id corresponding to the value type. @@ -168,7 +168,7 @@ inline const std::type_info* GenRuntimeTypeId() { // Flag help auxiliary structs. // This is help argument for absl::Flag encapsulating the string literal pointer -// or pointer to function generating it as well as enum descriminating two +// or pointer to function generating it as well as enum discriminating two // cases. using HelpGenFunc = std::string (*)(); @@ -901,7 +901,7 @@ void* FlagOps(FlagOp op, const void* v1, void* v2, void* v3) { case FlagOp::kSizeof: return reinterpret_cast(static_cast(sizeof(T))); case FlagOp::kFastTypeId: - return const_cast(absl::FastTypeId()); + return absl::bit_cast(absl::FastTypeId()); case FlagOp::kRuntimeTypeId: return const_cast(GenRuntimeTypeId()); case FlagOp::kParse: {