Use template instantiation declaration/definition for RTCStatsMember<T>.

This CL works around an "Explicit specialization after instantiation
error" when building with clang-cl and is_component_build=true (see
crbug.com/1018579). On top of that it uses "template instantiation
declarations/declarations" in order to avoid to instantiate the
template in clients code.

TBR: hbos@webrtc.org
Bug: webrtc:9419, chromium:1018579
Change-Id: I1b2862de678586afc81e8f7a407947322f8a06c4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/158795
Commit-Queue: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Yves Gerey <yvesg@google.com>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#29683}
diff --git a/api/DEPS b/api/DEPS
index f23b1b8..a86b42f 100644
--- a/api/DEPS
+++ b/api/DEPS
@@ -43,6 +43,7 @@
   ".*\.h": [
     "+rtc_base/checks.h",
     "+rtc_base/system/rtc_export.h",
+    "+rtc_base/system/rtc_export_template.h",
     "+rtc_base/units/unit_base.h",
     "+rtc_base/deprecation.h",
   ],
diff --git a/api/stats/rtc_stats.h b/api/stats/rtc_stats.h
index 0cfbc06..80a1276 100644
--- a/api/stats/rtc_stats.h
+++ b/api/stats/rtc_stats.h
@@ -21,6 +21,7 @@
 
 #include "rtc_base/checks.h"
 #include "rtc_base/system/rtc_export.h"
+#include "rtc_base/system/rtc_export_template.h"
 
 namespace webrtc {
 
@@ -267,7 +268,7 @@
 
   template <typename T>
   const T& cast_to() const {
-    RTC_DCHECK_EQ(type(), T::kType);
+    RTC_DCHECK_EQ(type(), T::StaticType());
     return static_cast<const T&>(*this);
   }
 
@@ -279,15 +280,12 @@
   bool is_defined_;
 };
 
-// Template implementation of |RTCStatsMemberInterface|. Every possible |T| is
-// specialized in rtcstats.cc, using a different |T| results in a linker error
-// (undefined reference to |kType|). The supported types are the ones described
-// by |RTCStatsMemberInterface::Type|.
+// Template implementation of |RTCStatsMemberInterface|.
+// The supported types are the ones described by
+// |RTCStatsMemberInterface::Type|.
 template <typename T>
 class RTC_EXPORT RTCStatsMember : public RTCStatsMemberInterface {
  public:
-  static const Type kType;
-
   explicit RTCStatsMember(const char* name)
       : RTCStatsMemberInterface(name, /*is_defined=*/false), value_() {}
   RTCStatsMember(const char* name, const T& value)
@@ -302,7 +300,8 @@
       : RTCStatsMemberInterface(other.name_, other.is_defined_),
         value_(std::move(other.value_)) {}
 
-  Type type() const override { return kType; }
+  static Type StaticType();
+  Type type() const override { return StaticType(); }
   bool is_sequence() const override;
   bool is_string() const override;
   bool is_standardized() const override { return true; }
@@ -356,6 +355,35 @@
   T value_;
 };
 
+#define WEBRTC_DECLARE_RTCSTATSMEMBER(T)                         \
+  template <>                                                    \
+  RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType(); \
+  template <>                                                    \
+  bool RTCStatsMember<T>::is_sequence() const;                   \
+  template <>                                                    \
+  bool RTCStatsMember<T>::is_string() const;                     \
+  template <>                                                    \
+  std::string RTCStatsMember<T>::ValueToString() const;          \
+  template <>                                                    \
+  std::string RTCStatsMember<T>::ValueToJson() 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>);
+
 // Using inheritance just so that it's obvious from the member's declaration
 // whether it's standardized or not.
 template <typename T>
diff --git a/stats/rtc_stats.cc b/stats/rtc_stats.cc
index f5139a7..92f64e4 100644
--- a/stats/rtc_stats.cc
+++ b/stats/rtc_stats.cc
@@ -128,8 +128,9 @@
 
 #define WEBRTC_DEFINE_RTCSTATSMEMBER(T, type, is_seq, is_str, to_str, to_json) \
   template <>                                                                  \
-  const RTCStatsMemberInterface::Type RTCStatsMember<T>::kType =               \
-      RTCStatsMemberInterface::type;                                           \
+  RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType() {              \
+    return type;                                                               \
+  }                                                                            \
   template <>                                                                  \
   bool RTCStatsMember<T>::is_sequence() const {                                \
     return is_seq;                                                             \
@@ -147,86 +148,87 @@
   std::string RTCStatsMember<T>::ValueToJson() const {                         \
     RTC_DCHECK(is_defined_);                                                   \
     return to_json;                                                            \
-  }
+  }                                                                            \
+  template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT) RTCStatsMember<T>
 
 WEBRTC_DEFINE_RTCSTATSMEMBER(bool,
                              kBool,
                              false,
                              false,
                              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_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(uint32_t,
                              kUint32,
                              false,
                              false,
                              rtc::ToString(value_),
-                             rtc::ToString(value_))
+                             rtc::ToString(value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(int64_t,
                              kInt64,
                              false,
                              false,
                              rtc::ToString(value_),
-                             ToStringAsDouble(value_))
+                             ToStringAsDouble(value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(uint64_t,
                              kUint64,
                              false,
                              false,
                              rtc::ToString(value_),
-                             ToStringAsDouble(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_)
+                             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_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int32_t>,
                              kSequenceInt32,
                              true,
                              false,
                              VectorToString(value_),
-                             VectorToString(value_))
+                             VectorToString(value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint32_t>,
                              kSequenceUint32,
                              true,
                              false,
                              VectorToString(value_),
-                             VectorToString(value_))
+                             VectorToString(value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int64_t>,
                              kSequenceInt64,
                              true,
                              false,
                              VectorToString(value_),
-                             VectorToStringAsDouble(value_))
+                             VectorToStringAsDouble(value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint64_t>,
                              kSequenceUint64,
                              true,
                              false,
                              VectorToString(value_),
-                             VectorToStringAsDouble(value_))
+                             VectorToStringAsDouble(value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<double>,
                              kSequenceDouble,
                              true,
                              false,
                              VectorToString(value_),
-                             VectorToStringAsDouble(value_))
+                             VectorToStringAsDouble(value_));
 WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<std::string>,
                              kSequenceString,
                              true,
                              false,
                              VectorOfStringsToString(value_),
-                             VectorOfStringsToString(value_))
+                             VectorOfStringsToString(value_));
 
 }  // namespace webrtc