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}
This commit is contained in:
Mirko Bonadei
2019-11-04 16:31:08 +01:00
committed by Commit Bot
parent bb56d4b0e2
commit 054f18513e
3 changed files with 56 additions and 25 deletions

View File

@ -43,6 +43,7 @@ specific_include_rules = {
".*\.h": [ ".*\.h": [
"+rtc_base/checks.h", "+rtc_base/checks.h",
"+rtc_base/system/rtc_export.h", "+rtc_base/system/rtc_export.h",
"+rtc_base/system/rtc_export_template.h",
"+rtc_base/units/unit_base.h", "+rtc_base/units/unit_base.h",
"+rtc_base/deprecation.h", "+rtc_base/deprecation.h",
], ],

View File

@ -21,6 +21,7 @@
#include "rtc_base/checks.h" #include "rtc_base/checks.h"
#include "rtc_base/system/rtc_export.h" #include "rtc_base/system/rtc_export.h"
#include "rtc_base/system/rtc_export_template.h"
namespace webrtc { namespace webrtc {
@ -267,7 +268,7 @@ class RTCStatsMemberInterface {
template <typename T> template <typename T>
const T& cast_to() const { const T& cast_to() const {
RTC_DCHECK_EQ(type(), T::kType); RTC_DCHECK_EQ(type(), T::StaticType());
return static_cast<const T&>(*this); return static_cast<const T&>(*this);
} }
@ -279,15 +280,12 @@ class RTCStatsMemberInterface {
bool is_defined_; bool is_defined_;
}; };
// Template implementation of |RTCStatsMemberInterface|. Every possible |T| is // Template implementation of |RTCStatsMemberInterface|.
// specialized in rtcstats.cc, using a different |T| results in a linker error // The supported types are the ones described by
// (undefined reference to |kType|). The supported types are the ones described // |RTCStatsMemberInterface::Type|.
// by |RTCStatsMemberInterface::Type|.
template <typename T> template <typename T>
class RTC_EXPORT RTCStatsMember : public RTCStatsMemberInterface { class RTC_EXPORT RTCStatsMember : public RTCStatsMemberInterface {
public: public:
static const Type kType;
explicit RTCStatsMember(const char* name) explicit RTCStatsMember(const char* name)
: RTCStatsMemberInterface(name, /*is_defined=*/false), value_() {} : RTCStatsMemberInterface(name, /*is_defined=*/false), value_() {}
RTCStatsMember(const char* name, const T& value) RTCStatsMember(const char* name, const T& value)
@ -302,7 +300,8 @@ class RTC_EXPORT RTCStatsMember : public RTCStatsMemberInterface {
: RTCStatsMemberInterface(other.name_, other.is_defined_), : RTCStatsMemberInterface(other.name_, other.is_defined_),
value_(std::move(other.value_)) {} 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_sequence() const override;
bool is_string() const override; bool is_string() const override;
bool is_standardized() const override { return true; } bool is_standardized() const override { return true; }
@ -356,6 +355,35 @@ class RTC_EXPORT RTCStatsMember : public RTCStatsMemberInterface {
T value_; 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 // Using inheritance just so that it's obvious from the member's declaration
// whether it's standardized or not. // whether it's standardized or not.
template <typename T> template <typename T>

View File

@ -128,8 +128,9 @@ RTCStats::MembersOfThisObjectAndAncestors(size_t additional_capacity) const {
#define WEBRTC_DEFINE_RTCSTATSMEMBER(T, type, is_seq, is_str, to_str, to_json) \ #define WEBRTC_DEFINE_RTCSTATSMEMBER(T, type, is_seq, is_str, to_str, to_json) \
template <> \ template <> \
const RTCStatsMemberInterface::Type RTCStatsMember<T>::kType = \ RTCStatsMemberInterface::Type RTCStatsMember<T>::StaticType() { \
RTCStatsMemberInterface::type; \ return type; \
} \
template <> \ template <> \
bool RTCStatsMember<T>::is_sequence() const { \ bool RTCStatsMember<T>::is_sequence() const { \
return is_seq; \ return is_seq; \
@ -147,86 +148,87 @@ RTCStats::MembersOfThisObjectAndAncestors(size_t additional_capacity) const {
std::string RTCStatsMember<T>::ValueToJson() const { \ std::string RTCStatsMember<T>::ValueToJson() const { \
RTC_DCHECK(is_defined_); \ RTC_DCHECK(is_defined_); \
return to_json; \ return to_json; \
} } \
template class RTC_EXPORT_TEMPLATE_DEFINE(RTC_EXPORT) RTCStatsMember<T>
WEBRTC_DEFINE_RTCSTATSMEMBER(bool, WEBRTC_DEFINE_RTCSTATSMEMBER(bool,
kBool, kBool,
false, false,
false, false,
rtc::ToString(value_), rtc::ToString(value_),
rtc::ToString(value_)) rtc::ToString(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(int32_t, WEBRTC_DEFINE_RTCSTATSMEMBER(int32_t,
kInt32, kInt32,
false, false,
false, false,
rtc::ToString(value_), rtc::ToString(value_),
rtc::ToString(value_)) rtc::ToString(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(uint32_t, WEBRTC_DEFINE_RTCSTATSMEMBER(uint32_t,
kUint32, kUint32,
false, false,
false, false,
rtc::ToString(value_), rtc::ToString(value_),
rtc::ToString(value_)) rtc::ToString(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(int64_t, WEBRTC_DEFINE_RTCSTATSMEMBER(int64_t,
kInt64, kInt64,
false, false,
false, false,
rtc::ToString(value_), rtc::ToString(value_),
ToStringAsDouble(value_)) ToStringAsDouble(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(uint64_t, WEBRTC_DEFINE_RTCSTATSMEMBER(uint64_t,
kUint64, kUint64,
false, false,
false, false,
rtc::ToString(value_), rtc::ToString(value_),
ToStringAsDouble(value_)) ToStringAsDouble(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(double, WEBRTC_DEFINE_RTCSTATSMEMBER(double,
kDouble, kDouble,
false, false,
false, false,
rtc::ToString(value_), rtc::ToString(value_),
ToStringAsDouble(value_)) ToStringAsDouble(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::string, kString, false, true, value_, value_) WEBRTC_DEFINE_RTCSTATSMEMBER(std::string, kString, false, true, value_, value_);
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<bool>, WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<bool>,
kSequenceBool, kSequenceBool,
true, true,
false, false,
VectorToString(value_), VectorToString(value_),
VectorToString(value_)) VectorToString(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int32_t>, WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int32_t>,
kSequenceInt32, kSequenceInt32,
true, true,
false, false,
VectorToString(value_), VectorToString(value_),
VectorToString(value_)) VectorToString(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint32_t>, WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint32_t>,
kSequenceUint32, kSequenceUint32,
true, true,
false, false,
VectorToString(value_), VectorToString(value_),
VectorToString(value_)) VectorToString(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int64_t>, WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<int64_t>,
kSequenceInt64, kSequenceInt64,
true, true,
false, false,
VectorToString(value_), VectorToString(value_),
VectorToStringAsDouble(value_)) VectorToStringAsDouble(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint64_t>, WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<uint64_t>,
kSequenceUint64, kSequenceUint64,
true, true,
false, false,
VectorToString(value_), VectorToString(value_),
VectorToStringAsDouble(value_)) VectorToStringAsDouble(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<double>, WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<double>,
kSequenceDouble, kSequenceDouble,
true, true,
false, false,
VectorToString(value_), VectorToString(value_),
VectorToStringAsDouble(value_)) VectorToStringAsDouble(value_));
WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<std::string>, WEBRTC_DEFINE_RTCSTATSMEMBER(std::vector<std::string>,
kSequenceString, kSequenceString,
true, true,
false, false,
VectorOfStringsToString(value_), VectorOfStringsToString(value_),
VectorOfStringsToString(value_)) VectorOfStringsToString(value_));
} // namespace webrtc } // namespace webrtc