Revert "[Stats] Make RTCStatsMember<T> a type alias for absl::optional<T>."

This reverts commit 79ac694d9b70fa9cd7b6a0f00bbee5d7fbbe64de.

Reason for revert: Breaks downstream (found another use of
ValueOrDefault instead of value_or)...

Original change's description:
> [Stats] Make RTCStatsMember<T> a type alias for absl::optional<T>.
>
> The moment we've all been waiting for.
>
> Step 1: Add type alias (this CL).
> Step 2: Migrate all uses of RTCStatsMember<T> to absl::optional<T>.
> Step 3: Delete type alias.
>
> Bug: webrtc:15164
> Change-Id: I00a7202c0b684fb2c57fcad4f501bccc167f1fa3
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/334680
> Commit-Queue: Henrik Boström <hbos@webrtc.org>
> Reviewed-by: Harald Alvestrand <hta@webrtc.org>
> Reviewed-by: Evan Shrubsole <eshr@google.com>
> Cr-Commit-Position: refs/heads/main@{#41593}

Bug: webrtc:15164
Change-Id: Ice3f44057b82a7ba9be000d9a0b714152fd07d2f
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/335701
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Evan Shrubsole <eshr@google.com>
Reviewed-by: Christoffer Dewerin <jansson@google.com>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41595}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index 2dba446..6af4fa5 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -774,6 +774,7 @@
     "stats/attribute.h",
     "stats/rtc_stats.h",
     "stats/rtc_stats_collector_callback.h",
+    "stats/rtc_stats_member.h",
     "stats/rtc_stats_report.h",
     "stats/rtcstats_objects.h",
   ]
diff --git a/api/stats/attribute.h b/api/stats/attribute.h
index d5fb290..09211f4 100644
--- a/api/stats/attribute.h
+++ b/api/stats/attribute.h
@@ -16,41 +16,37 @@
 #include <string>
 #include <vector>
 
-#include "absl/types/optional.h"
 #include "absl/types/variant.h"
-#include "rtc_base/checks.h"
+#include "api/stats/rtc_stats_member.h"
 #include "rtc_base/system/rtc_export.h"
 
 namespace webrtc {
 
-// TODO(https://crbug.com/webrtc/15164): Migrate all uses of RTCStatsMember to
-// absl::optional and delete this type alias.
-template <typename T>
-using RTCStatsMember = absl::optional<T>;
-
 // A light-weight wrapper of an RTCStats attribute (an individual metric).
 class RTC_EXPORT Attribute {
  public:
-  typedef absl::variant<const absl::optional<bool>*,
-                        const absl::optional<int32_t>*,
-                        const absl::optional<uint32_t>*,
-                        const absl::optional<int64_t>*,
-                        const absl::optional<uint64_t>*,
-                        const absl::optional<double>*,
-                        const absl::optional<std::string>*,
-                        const absl::optional<std::vector<bool>>*,
-                        const absl::optional<std::vector<int32_t>>*,
-                        const absl::optional<std::vector<uint32_t>>*,
-                        const absl::optional<std::vector<int64_t>>*,
-                        const absl::optional<std::vector<uint64_t>>*,
-                        const absl::optional<std::vector<double>>*,
-                        const absl::optional<std::vector<std::string>>*,
-                        const absl::optional<std::map<std::string, uint64_t>>*,
-                        const absl::optional<std::map<std::string, double>>*>
+  // TODO(https://crbug.com/webrtc/15164): Replace uses of RTCStatsMember<T>
+  // with absl::optional<T> and update these pointer types.
+  typedef absl::variant<const RTCStatsMember<bool>*,
+                        const RTCStatsMember<int32_t>*,
+                        const RTCStatsMember<uint32_t>*,
+                        const RTCStatsMember<int64_t>*,
+                        const RTCStatsMember<uint64_t>*,
+                        const RTCStatsMember<double>*,
+                        const RTCStatsMember<std::string>*,
+                        const RTCStatsMember<std::vector<bool>>*,
+                        const RTCStatsMember<std::vector<int32_t>>*,
+                        const RTCStatsMember<std::vector<uint32_t>>*,
+                        const RTCStatsMember<std::vector<int64_t>>*,
+                        const RTCStatsMember<std::vector<uint64_t>>*,
+                        const RTCStatsMember<std::vector<double>>*,
+                        const RTCStatsMember<std::vector<std::string>>*,
+                        const RTCStatsMember<std::map<std::string, uint64_t>>*,
+                        const RTCStatsMember<std::map<std::string, double>>*>
       StatVariant;
 
   template <typename T>
-  Attribute(const char* name, const absl::optional<T>* attribute)
+  explicit Attribute(const char* name, const RTCStatsMember<T>* attribute)
       : name_(name), attribute_(attribute) {}
 
   const char* name() const;
@@ -59,18 +55,21 @@
   bool has_value() const;
   template <typename T>
   bool holds_alternative() const {
-    return absl::holds_alternative<const absl::optional<T>*>(attribute_);
+    return absl::holds_alternative<const RTCStatsMember<T>*>(attribute_);
   }
   template <typename T>
-  const absl::optional<T>& as_optional() const {
+  absl::optional<T> as_optional() const {
     RTC_CHECK(holds_alternative<T>());
-    return *absl::get<const absl::optional<T>*>(attribute_);
+    if (!has_value()) {
+      return absl::nullopt;
+    }
+    return absl::optional<T>(get<T>());
   }
   template <typename T>
   const T& get() const {
     RTC_CHECK(holds_alternative<T>());
     RTC_CHECK(has_value());
-    return absl::get<const absl::optional<T>*>(attribute_)->value();
+    return absl::get<const RTCStatsMember<T>*>(attribute_)->value();
   }
 
   bool is_sequence() const;
diff --git a/api/stats/rtc_stats.h b/api/stats/rtc_stats.h
index 6781081..edd293f 100644
--- a/api/stats/rtc_stats.h
+++ b/api/stats/rtc_stats.h
@@ -21,6 +21,7 @@
 #include <vector>
 
 #include "api/stats/attribute.h"
+#include "api/stats/rtc_stats_member.h"
 #include "api/units/timestamp.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/system/rtc_export.h"
diff --git a/api/stats/rtc_stats_member.h b/api/stats/rtc_stats_member.h
new file mode 100644
index 0000000..9039569
--- /dev/null
+++ b/api/stats/rtc_stats_member.h
@@ -0,0 +1,185 @@
+/*
+ *  Copyright 2023 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef API_STATS_RTC_STATS_MEMBER_H_
+#define API_STATS_RTC_STATS_MEMBER_H_
+
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "absl/types/optional.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/system/rtc_export.h"
+#include "rtc_base/system/rtc_export_template.h"
+
+namespace webrtc {
+
+// Interface for `RTCStats` members, which have a name and a value of a type
+// defined in a subclass. Only the types listed in `Type` are supported, these
+// are implemented by `RTCStatsMember<T>`. The value of a member may be
+// undefined, the value can only be read if `is_defined`.
+class RTCStatsMemberInterface {
+ public:
+  // Member value types.
+  enum Type {
+    kBool,    // bool
+    kInt32,   // int32_t
+    kUint32,  // uint32_t
+    kInt64,   // int64_t
+    kUint64,  // uint64_t
+    kDouble,  // double
+    kString,  // std::string
+
+    kSequenceBool,    // std::vector<bool>
+    kSequenceInt32,   // std::vector<int32_t>
+    kSequenceUint32,  // std::vector<uint32_t>
+    kSequenceInt64,   // std::vector<int64_t>
+    kSequenceUint64,  // std::vector<uint64_t>
+    kSequenceDouble,  // std::vector<double>
+    kSequenceString,  // std::vector<std::string>
+
+    kMapStringUint64,  // std::map<std::string, uint64_t>
+    kMapStringDouble,  // std::map<std::string, double>
+  };
+
+  virtual ~RTCStatsMemberInterface() {}
+
+  virtual Type type() const = 0;
+  virtual bool is_sequence() const = 0;
+  virtual bool is_string() const = 0;
+  virtual bool has_value() const = 0;
+  // Type and value comparator. The names are not compared. These operators are
+  // exposed for testing.
+  bool operator==(const RTCStatsMemberInterface& other) const {
+    return IsEqual(other);
+  }
+  bool operator!=(const RTCStatsMemberInterface& other) const {
+    return !(*this == other);
+  }
+
+  virtual const RTCStatsMemberInterface* member_ptr() const { return this; }
+  template <typename T>
+  const T& cast_to() const {
+    RTC_DCHECK_EQ(type(), T::StaticType());
+    return static_cast<const T&>(*member_ptr());
+  }
+
+ protected:
+  virtual bool IsEqual(const RTCStatsMemberInterface& other) const = 0;
+};
+
+// Template implementation of `RTCStatsMemberInterface`.
+// The supported types are the ones described by
+// `RTCStatsMemberInterface::Type`.
+template <typename T>
+class RTCStatsMember : public RTCStatsMemberInterface {
+ public:
+  RTCStatsMember() {}
+  explicit RTCStatsMember(const T& value) : value_(value) {}
+
+  static Type StaticType();
+  Type type() const override { return StaticType(); }
+  bool is_sequence() const override;
+  bool is_string() const override;
+
+  template <typename U>
+  inline T value_or(U default_value) const {
+    return value_.value_or(default_value);
+  }
+  // TODO(https://crbug.com/webrtc/15164): Migrate to value_or() and delete.
+  template <typename U>
+  inline T ValueOrDefault(U default_value) const {
+    return value_or(default_value);
+  }
+
+  // Assignment operators.
+  T& operator=(const T& value) {
+    value_ = value;
+    return value_.value();
+  }
+  T& operator=(const T&& value) {
+    value_ = std::move(value);
+    return value_.value();
+  }
+
+  // Getter methods that look the same as absl::optional<T>. Please prefer these
+  // in order to unblock replacing RTCStatsMember<T> with absl::optional<T> in
+  // the future (https://crbug.com/webrtc/15164).
+  bool has_value() const override { return value_.has_value(); }
+  const T& value() const { return value_.value(); }
+  T& value() { return value_.value(); }
+  T& operator*() {
+    RTC_DCHECK(value_);
+    return *value_;
+  }
+  const T& operator*() const {
+    RTC_DCHECK(value_);
+    return *value_;
+  }
+  T* operator->() {
+    RTC_DCHECK(value_);
+    return &(*value_);
+  }
+  const T* operator->() const {
+    RTC_DCHECK(value_);
+    return &(*value_);
+  }
+
+  bool IsEqual(const RTCStatsMemberInterface& other) const override {
+    if (type() != other.type())
+      return false;
+    const RTCStatsMember<T>& other_t =
+        static_cast<const RTCStatsMember<T>&>(other);
+    return value_ == other_t.value_;
+  }
+
+ private:
+  absl::optional<T> value_;
+};
+
+namespace rtc_stats_internal {
+
+typedef std::map<std::string, uint64_t> MapStringUint64;
+typedef std::map<std::string, double> MapStringDouble;
+
+}  // namespace rtc_stats_internal
+
+#define WEBRTC_DECLARE_RTCSTATSMEMBER(T)                                    \
+  template <>                                                               \
+  RTC_EXPORT RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType(); \
+  template <>                                                               \
+  RTC_EXPORT bool RTCStatsMember<T>::is_sequence() const;                   \
+  template <>                                                               \
+  RTC_EXPORT bool RTCStatsMember<T>::is_string() const;                     \
+  extern template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)             \
+      RTCStatsMember<T>
+
+WEBRTC_DECLARE_RTCSTATSMEMBER(bool);
+WEBRTC_DECLARE_RTCSTATSMEMBER(int32_t);
+WEBRTC_DECLARE_RTCSTATSMEMBER(uint32_t);
+WEBRTC_DECLARE_RTCSTATSMEMBER(int64_t);
+WEBRTC_DECLARE_RTCSTATSMEMBER(uint64_t);
+WEBRTC_DECLARE_RTCSTATSMEMBER(double);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::string);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<bool>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int32_t>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint32_t>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<int64_t>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<uint64_t>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<double>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(std::vector<std::string>);
+WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64);
+WEBRTC_DECLARE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble);
+
+}  // namespace webrtc
+
+#endif  // API_STATS_RTC_STATS_MEMBER_H_
diff --git a/stats/BUILD.gn b/stats/BUILD.gn
index 76edc44..8993272 100644
--- a/stats/BUILD.gn
+++ b/stats/BUILD.gn
@@ -18,6 +18,7 @@
   sources = [
     "attribute.cc",
     "rtc_stats.cc",
+    "rtc_stats_member.cc",
     "rtc_stats_report.cc",
     "rtcstats_objects.cc",
   ]
diff --git a/stats/attribute.cc b/stats/attribute.cc
index cf49cb2..fab948b 100644
--- a/stats/attribute.cc
+++ b/stats/attribute.cc
@@ -25,12 +25,12 @@
 struct VisitIsSequence {
   // Any type of vector is a sequence.
   template <typename T>
-  bool operator()(const absl::optional<std::vector<T>>* attribute) {
+  bool operator()(const RTCStatsMember<std::vector<T>>* attribute) {
     return true;
   }
   // Any other type is not.
   template <typename T>
-  bool operator()(const absl::optional<T>* attribute) {
+  bool operator()(const RTCStatsMember<T>* attribute) {
     return false;
   }
 };
@@ -62,7 +62,7 @@
 
   // Vector attributes.
   template <typename T>
-  std::string operator()(const absl::optional<std::vector<T>>* attribute) {
+  std::string operator()(const RTCStatsMember<std::vector<T>>* attribute) {
     rtc::StringBuilder sb;
     sb << "[";
     const char* separator = "";
@@ -84,7 +84,7 @@
   // Map attributes.
   template <typename T>
   std::string operator()(
-      const absl::optional<std::map<std::string, T>>* attribute) {
+      const RTCStatsMember<std::map<std::string, T>>* attribute) {
     rtc::StringBuilder sb;
     sb << "{";
     const char* separator = "";
@@ -106,18 +106,21 @@
   }
   // Simple attributes.
   template <typename T>
-  std::string operator()(const absl::optional<T>* attribute) {
+  std::string operator()(const RTCStatsMember<T>* attribute) {
     return ValueToString(attribute->value());
   }
 };
 
 struct VisitIsEqual {
   template <typename T>
-  bool operator()(const absl::optional<T>* attribute) {
+  bool operator()(const RTCStatsMember<T>* attribute) {
     if (!other.holds_alternative<T>()) {
       return false;
     }
-    return *attribute == other.as_optional<T>();
+    absl::optional<T> attribute_as_optional =
+        attribute->has_value() ? absl::optional<T>(attribute->value())
+                               : absl::nullopt;
+    return attribute_as_optional == other.as_optional<T>();
   }
 
   const Attribute& other;
@@ -143,7 +146,7 @@
 }
 
 bool Attribute::is_string() const {
-  return absl::holds_alternative<const absl::optional<std::string>*>(
+  return absl::holds_alternative<const RTCStatsMember<std::string>*>(
       attribute_);
 }
 
diff --git a/stats/rtc_stats_member.cc b/stats/rtc_stats_member.cc
new file mode 100644
index 0000000..3f91988
--- /dev/null
+++ b/stats/rtc_stats_member.cc
@@ -0,0 +1,62 @@
+/*
+ *  Copyright 2023 The WebRTC Project Authors. All rights reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "api/stats/rtc_stats_member.h"
+
+namespace webrtc {
+
+#define WEBRTC_DEFINE_RTCSTATSMEMBER(T, type, is_seq, is_str)     \
+  template <>                                                     \
+  RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType() { \
+    return type;                                                  \
+  }                                                               \
+  template <>                                                     \
+  bool RTCStatsMember<T>::is_sequence() const {                   \
+    return is_seq;                                                \
+  }                                                               \
+  template <>                                                     \
+  bool RTCStatsMember<T>::is_string() const {                     \
+    return is_str;                                                \
+  }                                                               \
+  template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT) RTCStatsMember<T>
+
+WEBRTC_DEFINE_RTCSTATSMEMBER(bool, kBool, false, false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(int32_t, kInt32, false, false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(uint32_t, kUint32, false, false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(int64_t, kInt64, false, false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(uint64_t, kUint64, false, false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(double, kDouble, false, false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::string, kString, false, true);
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<bool>, kSequenceBool, true, false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int32_t>, kSequenceInt32, true, false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint32_t>,
+                             kSequenceUint32,
+                             true,
+                             false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int64_t>, kSequenceInt64, true, false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint64_t>,
+                             kSequenceUint64,
+                             true,
+                             false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<double>, kSequenceDouble, true, false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<std::string>,
+                             kSequenceString,
+                             true,
+                             false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64,
+                             kMapStringUint64,
+                             false,
+                             false);
+WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble,
+                             kMapStringDouble,
+                             false,
+                             false);
+
+}  // namespace webrtc
diff --git a/stats/rtc_stats_unittest.cc b/stats/rtc_stats_unittest.cc
index 1098f04..fd90692 100644
--- a/stats/rtc_stats_unittest.cc
+++ b/stats/rtc_stats_unittest.cc
@@ -166,8 +166,7 @@
   stats_with_all_values.m_map_string_double = std::map<std::string, double>();
   EXPECT_NE(stats_with_all_values, empty_stats);
   EXPECT_EQ(stats_with_all_values, stats_with_all_values);
-  EXPECT_NE(stats_with_all_values.GetAttribute(stats_with_all_values.m_int32),
-            stats_with_all_values.GetAttribute(stats_with_all_values.m_uint32));
+  EXPECT_NE(stats_with_all_values.m_int32, stats_with_all_values.m_uint32);
 
   RTCTestStats one_member_different[] = {
       stats_with_all_values, stats_with_all_values, stats_with_all_values,
@@ -393,42 +392,71 @@
 
 TEST(RTCStatsTest, IsSequence) {
   RTCTestStats stats("statsId", Timestamp::Micros(42));
-  EXPECT_FALSE(stats.GetAttribute(stats.m_bool).is_sequence());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_int32).is_sequence());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_uint32).is_sequence());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_int64).is_sequence());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_uint64).is_sequence());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_double).is_sequence());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_string).is_sequence());
-  EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_bool).is_sequence());
-  EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_int32).is_sequence());
-  EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_uint32).is_sequence());
-  EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_int64).is_sequence());
-  EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_uint64).is_sequence());
-  EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_double).is_sequence());
-  EXPECT_TRUE(stats.GetAttribute(stats.m_sequence_string).is_sequence());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_map_string_uint64).is_sequence());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_map_string_double).is_sequence());
+  EXPECT_FALSE(stats.m_bool.is_sequence());
+  EXPECT_FALSE(stats.m_int32.is_sequence());
+  EXPECT_FALSE(stats.m_uint32.is_sequence());
+  EXPECT_FALSE(stats.m_int64.is_sequence());
+  EXPECT_FALSE(stats.m_uint64.is_sequence());
+  EXPECT_FALSE(stats.m_double.is_sequence());
+  EXPECT_FALSE(stats.m_string.is_sequence());
+  EXPECT_TRUE(stats.m_sequence_bool.is_sequence());
+  EXPECT_TRUE(stats.m_sequence_int32.is_sequence());
+  EXPECT_TRUE(stats.m_sequence_uint32.is_sequence());
+  EXPECT_TRUE(stats.m_sequence_int64.is_sequence());
+  EXPECT_TRUE(stats.m_sequence_uint64.is_sequence());
+  EXPECT_TRUE(stats.m_sequence_double.is_sequence());
+  EXPECT_TRUE(stats.m_sequence_string.is_sequence());
+  EXPECT_FALSE(stats.m_map_string_uint64.is_sequence());
+  EXPECT_FALSE(stats.m_map_string_double.is_sequence());
+}
+
+TEST(RTCStatsTest, Type) {
+  RTCTestStats stats("statsId", Timestamp::Micros(42));
+  EXPECT_EQ(RTCStatsMemberInterface::kBool, stats.m_bool.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kInt32, stats.m_int32.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kUint32, stats.m_uint32.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kInt64, stats.m_int64.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kUint64, stats.m_uint64.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kDouble, stats.m_double.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kString, stats.m_string.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kSequenceBool,
+            stats.m_sequence_bool.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kSequenceInt32,
+            stats.m_sequence_int32.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kSequenceUint32,
+            stats.m_sequence_uint32.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kSequenceInt64,
+            stats.m_sequence_int64.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kSequenceUint64,
+            stats.m_sequence_uint64.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kSequenceDouble,
+            stats.m_sequence_double.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kSequenceString,
+            stats.m_sequence_string.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kMapStringUint64,
+            stats.m_map_string_uint64.type());
+  EXPECT_EQ(RTCStatsMemberInterface::kMapStringDouble,
+            stats.m_map_string_double.type());
 }
 
 TEST(RTCStatsTest, IsString) {
   RTCTestStats stats("statsId", Timestamp::Micros(42));
-  EXPECT_TRUE(stats.GetAttribute(stats.m_string).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_bool).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_int32).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_uint32).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_int64).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_uint64).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_double).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_bool).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_int32).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_uint32).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_int64).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_uint64).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_double).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_sequence_string).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_map_string_uint64).is_string());
-  EXPECT_FALSE(stats.GetAttribute(stats.m_map_string_double).is_string());
+  EXPECT_TRUE(stats.m_string.is_string());
+  EXPECT_FALSE(stats.m_bool.is_string());
+  EXPECT_FALSE(stats.m_int32.is_string());
+  EXPECT_FALSE(stats.m_uint32.is_string());
+  EXPECT_FALSE(stats.m_int64.is_string());
+  EXPECT_FALSE(stats.m_uint64.is_string());
+  EXPECT_FALSE(stats.m_double.is_string());
+  EXPECT_FALSE(stats.m_sequence_bool.is_string());
+  EXPECT_FALSE(stats.m_sequence_int32.is_string());
+  EXPECT_FALSE(stats.m_sequence_uint32.is_string());
+  EXPECT_FALSE(stats.m_sequence_int64.is_string());
+  EXPECT_FALSE(stats.m_sequence_uint64.is_string());
+  EXPECT_FALSE(stats.m_sequence_double.is_string());
+  EXPECT_FALSE(stats.m_sequence_string.is_string());
+  EXPECT_FALSE(stats.m_map_string_uint64.is_string());
+  EXPECT_FALSE(stats.m_map_string_double.is_string());
 }
 
 TEST(RTCStatsTest, AttributeToString) {