Relanding #128202 Adding support for enum class in RTC_CHECK and RTC_LOG.

This is a reland of: https://webrtc-review.googlesource.com/c/src/+/128202
Logging unit test has been fixed to unregister the log listener.

Bug: webrtc:10418
Change-Id: Idac9cb71807e16a585ccb7e3e4271aa45d69f547
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/128541
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Commit-Queue: Amit Hilbuch <amithi@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27192}
This commit is contained in:
Amit Hilbuch 2019-03-18 13:09:18 -07:00 committed by Commit Bot
parent 1f850a6dc7
commit 10c5a93eb7
3 changed files with 58 additions and 24 deletions

View file

@ -168,6 +168,16 @@ inline Val<CheckArgType::kVoidP, const void*> MakeVal(const void* x) {
return {x}; return {x};
} }
// The enum class types are not implicitly convertible to arithmetic types.
template <
typename T,
typename std::enable_if<std::is_enum<T>::value &&
!std::is_arithmetic<T>::value>::type* = nullptr>
inline decltype(MakeVal(std::declval<typename std::underlying_type<T>::type>()))
MakeVal(T x) {
return {static_cast<typename std::underlying_type<T>::type>(x)};
}
// Ephemeral type that represents the result of the logging << operator. // Ephemeral type that represents the result of the logging << operator.
template <typename... Ts> template <typename... Ts>
class LogStreamer; class LogStreamer;
@ -176,18 +186,18 @@ class LogStreamer;
template <> template <>
class LogStreamer<> final { class LogStreamer<> final {
public: public:
template < template <typename U,
typename U, typename std::enable_if<std::is_arithmetic<U>::value ||
typename std::enable_if<std::is_arithmetic<U>::value>::type* = nullptr> std::is_enum<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>()))> operator<<( RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>()))> operator<<(
U arg) const { U arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>()))>(MakeVal(arg), return LogStreamer<decltype(MakeVal(std::declval<U>()))>(MakeVal(arg),
this); this);
} }
template < template <typename U,
typename U, typename std::enable_if<!std::is_arithmetic<U>::value &&
typename std::enable_if<!std::is_arithmetic<U>::value>::type* = nullptr> !std::is_enum<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>()))> operator<<( RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>()))> operator<<(
const U& arg) const { const U& arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>()))>(MakeVal(arg), return LogStreamer<decltype(MakeVal(std::declval<U>()))>(MakeVal(arg),
@ -222,18 +232,18 @@ class LogStreamer<T, Ts...> final {
RTC_FORCE_INLINE LogStreamer(T arg, const LogStreamer<Ts...>* prior) RTC_FORCE_INLINE LogStreamer(T arg, const LogStreamer<Ts...>* prior)
: arg_(arg), prior_(prior) {} : arg_(arg), prior_(prior) {}
template < template <typename U,
typename U, typename std::enable_if<std::is_arithmetic<U>::value ||
typename std::enable_if<std::is_arithmetic<U>::value>::type* = nullptr> std::is_enum<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...> RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>
operator<<(U arg) const { operator<<(U arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>( return LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>(
MakeVal(arg), this); MakeVal(arg), this);
} }
template < template <typename U,
typename U, typename std::enable_if<!std::is_arithmetic<U>::value &&
typename std::enable_if<!std::is_arithmetic<U>::value>::type* = nullptr> !std::is_enum<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...> RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>
operator<<(const U& arg) const { operator<<(const U& arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>( return LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>(

View file

@ -248,6 +248,16 @@ inline Val<LogArgType::kLogMetadataErr, LogMetadataErr> MakeVal(
return {x}; return {x};
} }
// The enum class types are not implicitly convertible to arithmetic types.
template <
typename T,
typename std::enable_if<std::is_enum<T>::value &&
!std::is_arithmetic<T>::value>::type* = nullptr>
inline decltype(MakeVal(std::declval<typename std::underlying_type<T>::type>()))
MakeVal(T x) {
return {static_cast<typename std::underlying_type<T>::type>(x)};
}
#ifdef WEBRTC_ANDROID #ifdef WEBRTC_ANDROID
inline Val<LogArgType::kLogMetadataTag, LogMetadataTag> MakeVal( inline Val<LogArgType::kLogMetadataTag, LogMetadataTag> MakeVal(
const LogMetadataTag& x) { const LogMetadataTag& x) {
@ -285,18 +295,18 @@ class LogStreamer;
template <> template <>
class LogStreamer<> final { class LogStreamer<> final {
public: public:
template < template <typename U,
typename U, typename std::enable_if<std::is_arithmetic<U>::value ||
typename std::enable_if<std::is_arithmetic<U>::value>::type* = nullptr> std::is_enum<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>()))> operator<<( RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>()))> operator<<(
U arg) const { U arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>()))>(MakeVal(arg), return LogStreamer<decltype(MakeVal(std::declval<U>()))>(MakeVal(arg),
this); this);
} }
template < template <typename U,
typename U, typename std::enable_if<!std::is_arithmetic<U>::value &&
typename std::enable_if<!std::is_arithmetic<U>::value>::type* = nullptr> !std::is_enum<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>()))> operator<<( RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>()))> operator<<(
const U& arg) const { const U& arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>()))>(MakeVal(arg), return LogStreamer<decltype(MakeVal(std::declval<U>()))>(MakeVal(arg),
@ -318,18 +328,18 @@ class LogStreamer<T, Ts...> final {
RTC_FORCE_INLINE LogStreamer(T arg, const LogStreamer<Ts...>* prior) RTC_FORCE_INLINE LogStreamer(T arg, const LogStreamer<Ts...>* prior)
: arg_(arg), prior_(prior) {} : arg_(arg), prior_(prior) {}
template < template <typename U,
typename U, typename std::enable_if<std::is_arithmetic<U>::value ||
typename std::enable_if<std::is_arithmetic<U>::value>::type* = nullptr> std::is_enum<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...> RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>
operator<<(U arg) const { operator<<(U arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>( return LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>(
MakeVal(arg), this); MakeVal(arg), this);
} }
template < template <typename U,
typename U, typename std::enable_if<!std::is_arithmetic<U>::value &&
typename std::enable_if<!std::is_arithmetic<U>::value>::type* = nullptr> !std::is_enum<U>::value>::type* = nullptr>
RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...> RTC_FORCE_INLINE LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>
operator<<(const U& arg) const { operator<<(const U& arg) const {
return LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>( return LogStreamer<decltype(MakeVal(std::declval<U>())), T, Ts...>(

View file

@ -368,4 +368,18 @@ TEST(LogTest, Perf) {
<< " total bytes logged: " << str.size(); << " total bytes logged: " << str.size();
} }
TEST(LogTest, EnumsAreSupported) {
enum class TestEnum { kValue0 = 0, kValue1 = 1 };
std::string str;
LogSinkImpl<StringStream> stream(&str);
LogMessage::AddLogToStream(&stream, LS_INFO);
RTC_LOG(LS_INFO) << "[" << TestEnum::kValue0 << "]";
EXPECT_NE(std::string::npos, str.find("[0]"));
EXPECT_EQ(std::string::npos, str.find("[1]"));
RTC_LOG(LS_INFO) << "[" << TestEnum::kValue1 << "]";
EXPECT_NE(std::string::npos, str.find("[1]"));
LogMessage::RemoveLogToStream(&stream);
stream.Close();
}
} // namespace rtc } // namespace rtc