Convert FastTypeIdType from an alias to a struct.

PiperOrigin-RevId: 853275176
Change-Id: I03979c49739d1664ede2fa9be1034ddeb379447d
diff --git a/absl/base/fast_type_id.h b/absl/base/fast_type_id.h
index ff25027..a1214da 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 <utility>
+
 #include "absl/base/config.h"
 
 namespace absl {
@@ -29,14 +31,40 @@
 }  // namespace base_internal
 
 // The type returned by `absl::FastTypeId<T>()`.
-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<T>()`.
+  constexpr FastTypeIdType() = default;
+
+  template <typename H>
+  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<T>()` is the generator method for FastTypeIdType values.
+  template <typename T>
+  friend constexpr FastTypeIdType FastTypeId();
+
+  explicit constexpr FastTypeIdType(const void* ptr) : ptr_(ptr) {}
+
+  const void* ptr_ = nullptr;
+};
 
 // `absl::FastTypeId<Type>()` 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 <typename Type>
 constexpr FastTypeIdType FastTypeId() {
-  return &base_internal::FastTypeTag<Type>::kDummyVar;
+  return FastTypeIdType(&base_internal::FastTypeTag<Type>::kDummyVar);
 }
 
 ABSL_NAMESPACE_END
diff --git a/absl/base/fast_type_id_test.cc b/absl/base/fast_type_id_test.cc
index 3068e4b..d27d9fa 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 cab9d16..285d842 100644
--- a/absl/flags/internal/flag.h
+++ b/absl/flags/internal/flag.h
@@ -135,7 +135,7 @@
 }
 // Returns fast type id corresponding to the value type.
 inline FlagFastTypeId FastTypeId(FlagOpFn op) {
-  return reinterpret_cast<FlagFastTypeId>(
+  return absl::bit_cast<FlagFastTypeId>(
       op(FlagOp::kFastTypeId, nullptr, nullptr, nullptr));
 }
 // Returns fast type id corresponding to the value type.
@@ -168,7 +168,7 @@
 // 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 @@
     case FlagOp::kSizeof:
       return reinterpret_cast<void*>(static_cast<uintptr_t>(sizeof(T)));
     case FlagOp::kFastTypeId:
-      return const_cast<void*>(absl::FastTypeId<T>());
+      return absl::bit_cast<void*>(absl::FastTypeId<T>());
     case FlagOp::kRuntimeTypeId:
       return const_cast<std::type_info*>(GenRuntimeTypeId<T>());
     case FlagOp::kParse: {