stats: use absl::optional to represent value

which is a more modern way to represent something that either has a value or is not set

BUG=webrtc:14544

Change-Id: I0a06b30b1c7f802247eb1f60e69271594b94a6f0
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/278421
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Commit-Queue: Philipp Hancke <phancke@microsoft.com>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38443}
diff --git a/api/BUILD.gn b/api/BUILD.gn
index 6c9414e..147a8c1 100644
--- a/api/BUILD.gn
+++ b/api/BUILD.gn
@@ -708,6 +708,8 @@
     "../rtc_base/system:rtc_export",
     "units:timestamp",
   ]
+
+  absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
 }
 
 rtc_library("audio_options_api") {
diff --git a/api/stats/rtc_stats.h b/api/stats/rtc_stats.h
index e22043d..273ea31 100644
--- a/api/stats/rtc_stats.h
+++ b/api/stats/rtc_stats.h
@@ -20,6 +20,7 @@
 #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"
@@ -260,7 +261,7 @@
   virtual Type type() const = 0;
   virtual bool is_sequence() const = 0;
   virtual bool is_string() const = 0;
-  bool is_defined() const { return is_defined_; }
+  virtual bool is_defined() const = 0;
   // Is this part of the stats spec? Used so that chromium can easily filter
   // out anything unstandardized.
   virtual bool is_standardized() const = 0;
@@ -296,13 +297,11 @@
   }
 
  protected:
-  RTCStatsMemberInterface(const char* name, bool is_defined)
-      : name_(name), is_defined_(is_defined) {}
+  explicit RTCStatsMemberInterface(const char* name) : name_(name) {}
 
   virtual bool IsEqual(const RTCStatsMemberInterface& other) const = 0;
 
   const char* const name_;
-  bool is_defined_;
 };
 
 // Template implementation of `RTCStatsMemberInterface`.
@@ -312,70 +311,58 @@
 class RTCStatsMember : public RTCStatsMemberInterface {
  public:
   explicit RTCStatsMember(const char* name)
-      : RTCStatsMemberInterface(name,
-                                /*is_defined=*/false),
-        value_() {}
+      : RTCStatsMemberInterface(name), value_() {}
   RTCStatsMember(const char* name, const T& value)
-      : RTCStatsMemberInterface(name,
-                                /*is_defined=*/true),
-        value_(value) {}
+      : RTCStatsMemberInterface(name), value_(value) {}
   RTCStatsMember(const char* name, T&& value)
-      : RTCStatsMemberInterface(name,
-                                /*is_defined=*/true),
-        value_(std::move(value)) {}
-  RTCStatsMember(const RTCStatsMember<T>& other)
-      : RTCStatsMemberInterface(other.name_, other.is_defined_),
-        value_(other.value_) {}
-  RTCStatsMember(RTCStatsMember<T>&& other)
-      : RTCStatsMemberInterface(other.name_, other.is_defined_),
-        value_(std::move(other.value_)) {}
+      : RTCStatsMemberInterface(name), value_(std::move(value)) {}
+  explicit RTCStatsMember(const RTCStatsMember<T>& other)
+      : RTCStatsMemberInterface(other.name_), value_(other.value_) {}
+  explicit RTCStatsMember(RTCStatsMember<T>&& other)
+      : RTCStatsMemberInterface(other.name_), value_(std::move(other.value_)) {}
 
   static Type StaticType();
   Type type() const override { return StaticType(); }
   bool is_sequence() const override;
   bool is_string() const override;
+  bool is_defined() const override { return value_.has_value(); }
   bool is_standardized() const override { return true; }
   std::string ValueToString() const override;
   std::string ValueToJson() const override;
 
   template <typename U>
   inline T ValueOrDefault(U default_value) const {
-    if (is_defined()) {
-      return *(*this);
-    }
-    return default_value;
+    return value_.value_or(default_value);
   }
 
   // Assignment operators.
   T& operator=(const T& value) {
     value_ = value;
-    is_defined_ = true;
-    return value_;
+    return value_.value();
   }
   T& operator=(const T&& value) {
     value_ = std::move(value);
-    is_defined_ = true;
-    return value_;
+    return value_.value();
   }
 
   // Value getters.
   T& operator*() {
-    RTC_DCHECK(is_defined_);
-    return value_;
+    RTC_DCHECK(value_);
+    return *value_;
   }
   const T& operator*() const {
-    RTC_DCHECK(is_defined_);
-    return value_;
+    RTC_DCHECK(value_);
+    return *value_;
   }
 
   // Value getters, arrow operator.
   T* operator->() {
-    RTC_DCHECK(is_defined_);
-    return &value_;
+    RTC_DCHECK(value_);
+    return &(*value_);
   }
   const T* operator->() const {
-    RTC_DCHECK(is_defined_);
-    return &value_;
+    RTC_DCHECK(value_);
+    return &(*value_);
   }
 
  protected:
@@ -386,15 +373,11 @@
       return false;
     const RTCStatsMember<T>& other_t =
         static_cast<const RTCStatsMember<T>&>(other);
-    if (!is_defined_)
-      return !other_t.is_defined();
-    if (!other.is_defined())
-      return false;
     return value_ == other_t.value_;
   }
 
  private:
-  T value_;
+  absl::optional<T> value_;
 };
 
 namespace rtc_stats_internal {
diff --git a/stats/rtc_stats.cc b/stats/rtc_stats.cc
index 375e1f7..e556db6 100644
--- a/stats/rtc_stats.cc
+++ b/stats/rtc_stats.cc
@@ -187,12 +187,12 @@
   }                                                                            \
   template <>                                                                  \
   std::string RTCStatsMember<T>::ValueToString() const {                       \
-    RTC_DCHECK(is_defined_);                                                   \
+    RTC_DCHECK(value_.has_value());                                            \
     return to_str;                                                             \
   }                                                                            \
   template <>                                                                  \
   std::string RTCStatsMember<T>::ValueToJson() const {                         \
-    RTC_DCHECK(is_defined_);                                                   \
+    RTC_DCHECK(value_.has_value());                                            \
     return to_json;                                                            \
   }                                                                            \
   template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT) RTCStatsMember<T>
@@ -201,93 +201,98 @@
                              kBool,
                              false,
                              false,
-                             rtc::ToString(value_),
-                             rtc::ToString(value_));
+                             rtc::ToString(*value_),
+                             rtc::ToString(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(int32_t,
                              kInt32,
                              false,
                              false,
-                             rtc::ToString(value_),
-                             rtc::ToString(value_));
+                             rtc::ToString(*value_),
+                             rtc::ToString(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(uint32_t,
                              kUint32,
                              false,
                              false,
-                             rtc::ToString(value_),
-                             rtc::ToString(value_));
+                             rtc::ToString(*value_),
+                             rtc::ToString(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(int64_t,
                              kInt64,
                              false,
                              false,
-                             rtc::ToString(value_),
-                             ToStringAsDouble(value_));
+                             rtc::ToString(*value_),
+                             ToStringAsDouble(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(uint64_t,
                              kUint64,
                              false,
                              false,
-                             rtc::ToString(value_),
-                             ToStringAsDouble(value_));
+                             rtc::ToString(*value_),
+                             ToStringAsDouble(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(double,
                              kDouble,
                              false,
                              false,
-                             rtc::ToString(value_),
-                             ToStringAsDouble(value_));
-WEBRTC_DEFINE_RTCSTATSMEMBER(std::string, kString, false, true, value_, value_);
+                             rtc::ToString(*value_),
+                             ToStringAsDouble(*value_));
+WEBRTC_DEFINE_RTCSTATSMEMBER(std::string,
+                             kString,
+                             false,
+                             true,
+                             *value_,
+                             *value_);
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<bool>,
                              kSequenceBool,
                              true,
                              false,
-                             VectorToString(value_),
-                             VectorToString(value_));
+                             VectorToString(*value_),
+                             VectorToString(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int32_t>,
                              kSequenceInt32,
                              true,
                              false,
-                             VectorToString(value_),
-                             VectorToString(value_));
+                             VectorToString(*value_),
+                             VectorToString(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint32_t>,
                              kSequenceUint32,
                              true,
                              false,
-                             VectorToString(value_),
-                             VectorToString(value_));
+                             VectorToString(*value_),
+                             VectorToString(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int64_t>,
                              kSequenceInt64,
                              true,
                              false,
-                             VectorToString(value_),
-                             VectorToStringAsDouble(value_));
+                             VectorToString(*value_),
+                             VectorToStringAsDouble(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint64_t>,
                              kSequenceUint64,
                              true,
                              false,
-                             VectorToString(value_),
-                             VectorToStringAsDouble(value_));
+                             VectorToString(*value_),
+                             VectorToStringAsDouble(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<double>,
                              kSequenceDouble,
                              true,
                              false,
-                             VectorToString(value_),
-                             VectorToStringAsDouble(value_));
+                             VectorToString(*value_),
+                             VectorToStringAsDouble(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<std::string>,
                              kSequenceString,
                              true,
                              false,
-                             VectorOfStringsToString(value_),
-                             VectorOfStringsToString(value_));
+                             VectorOfStringsToString(*value_),
+                             VectorOfStringsToString(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringUint64,
                              kMapStringUint64,
                              false,
                              false,
-                             MapToString(value_),
-                             MapToStringAsDouble(value_));
+                             MapToString(*value_),
+                             MapToStringAsDouble(*value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(rtc_stats_internal::MapStringDouble,
                              kMapStringDouble,
                              false,
                              false,
-                             MapToString(value_),
-                             MapToStringAsDouble(value_));
+                             MapToString(*value_),
+                             MapToStringAsDouble(*value_));
 
 // Restricted members that expose hardware capabilites.
 template class RTC_EXPORT_TEMPLATE_DECLARE(RTC_EXPORT)