From 6b6f537e839ee32d72b69f1f6dc3747fbd12b3eb Mon Sep 17 00:00:00 2001 From: Amit Hilbuch Date: Fri, 15 Mar 2019 16:55:17 -0700 Subject: [PATCH] Adding support for enum class in RTC_CHECK and RTC_LOG. Enum class types are by design not convertible to arithmetic types. As a result they are currently not supported in RTC_CHECK and RTC_LOG. The current workaround was to use something like RTC_CHECK(v1 == v2) instead of RTC_CHECK_EQ(v1, v2). This change adds support for any enum class type by converting it to the underlying type. Bug: webrtc:10418 Change-Id: I59e6608e6a97a4cc007c903f8e021a58d4c49ff8 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/128202 Reviewed-by: Karl Wiberg Commit-Queue: Amit Hilbuch Cr-Commit-Position: refs/heads/master@{#27166} --- rtc_base/checks.h | 34 ++++++++++++++++++++++------------ rtc_base/logging.h | 34 ++++++++++++++++++++++------------ rtc_base/logging_unittest.cc | 12 ++++++++++++ 3 files changed, 56 insertions(+), 24 deletions(-) diff --git a/rtc_base/checks.h b/rtc_base/checks.h index 2694258fe5..b351ad2e21 100644 --- a/rtc_base/checks.h +++ b/rtc_base/checks.h @@ -168,6 +168,16 @@ inline Val MakeVal(const void* x) { return {x}; } +// The enum class types are not implicitly convertible to arithmetic types. +template < + typename T, + typename std::enable_if::value && + !std::is_arithmetic::value>::type* = nullptr> +inline decltype(MakeVal(std::declval::type>())) +MakeVal(T x) { + return {static_cast::type>(x)}; +} + // Ephemeral type that represents the result of the logging << operator. template class LogStreamer; @@ -176,18 +186,18 @@ class LogStreamer; template <> class LogStreamer<> final { public: - template < - typename U, - typename std::enable_if::value>::type* = nullptr> + template ::value || + std::is_enum::value>::type* = nullptr> RTC_FORCE_INLINE LogStreamer()))> operator<<( U arg) const { return LogStreamer()))>(MakeVal(arg), this); } - template < - typename U, - typename std::enable_if::value>::type* = nullptr> + template ::value && + !std::is_enum::value>::type* = nullptr> RTC_FORCE_INLINE LogStreamer()))> operator<<( const U& arg) const { return LogStreamer()))>(MakeVal(arg), @@ -222,18 +232,18 @@ class LogStreamer final { RTC_FORCE_INLINE LogStreamer(T arg, const LogStreamer* prior) : arg_(arg), prior_(prior) {} - template < - typename U, - typename std::enable_if::value>::type* = nullptr> + template ::value || + std::is_enum::value>::type* = nullptr> RTC_FORCE_INLINE LogStreamer())), T, Ts...> operator<<(U arg) const { return LogStreamer())), T, Ts...>( MakeVal(arg), this); } - template < - typename U, - typename std::enable_if::value>::type* = nullptr> + template ::value && + !std::is_enum::value>::type* = nullptr> RTC_FORCE_INLINE LogStreamer())), T, Ts...> operator<<(const U& arg) const { return LogStreamer())), T, Ts...>( diff --git a/rtc_base/logging.h b/rtc_base/logging.h index 5cd4f72f22..3f48eeb0de 100644 --- a/rtc_base/logging.h +++ b/rtc_base/logging.h @@ -248,6 +248,16 @@ inline Val MakeVal( return {x}; } +// The enum class types are not implicitly convertible to arithmetic types. +template < + typename T, + typename std::enable_if::value && + !std::is_arithmetic::value>::type* = nullptr> +inline decltype(MakeVal(std::declval::type>())) +MakeVal(T x) { + return {static_cast::type>(x)}; +} + #ifdef WEBRTC_ANDROID inline Val MakeVal( const LogMetadataTag& x) { @@ -285,18 +295,18 @@ class LogStreamer; template <> class LogStreamer<> final { public: - template < - typename U, - typename std::enable_if::value>::type* = nullptr> + template ::value || + std::is_enum::value>::type* = nullptr> RTC_FORCE_INLINE LogStreamer()))> operator<<( U arg) const { return LogStreamer()))>(MakeVal(arg), this); } - template < - typename U, - typename std::enable_if::value>::type* = nullptr> + template ::value && + !std::is_enum::value>::type* = nullptr> RTC_FORCE_INLINE LogStreamer()))> operator<<( const U& arg) const { return LogStreamer()))>(MakeVal(arg), @@ -318,18 +328,18 @@ class LogStreamer final { RTC_FORCE_INLINE LogStreamer(T arg, const LogStreamer* prior) : arg_(arg), prior_(prior) {} - template < - typename U, - typename std::enable_if::value>::type* = nullptr> + template ::value || + std::is_enum::value>::type* = nullptr> RTC_FORCE_INLINE LogStreamer())), T, Ts...> operator<<(U arg) const { return LogStreamer())), T, Ts...>( MakeVal(arg), this); } - template < - typename U, - typename std::enable_if::value>::type* = nullptr> + template ::value && + !std::is_enum::value>::type* = nullptr> RTC_FORCE_INLINE LogStreamer())), T, Ts...> operator<<(const U& arg) const { return LogStreamer())), T, Ts...>( diff --git a/rtc_base/logging_unittest.cc b/rtc_base/logging_unittest.cc index e49440dce1..4f05ac00cf 100644 --- a/rtc_base/logging_unittest.cc +++ b/rtc_base/logging_unittest.cc @@ -368,4 +368,16 @@ TEST(LogTest, Perf) { << " total bytes logged: " << str.size(); } +TEST(LogTest, EnumsAreSupported) { + enum class TestEnum { kValue0 = 0, kValue1 = 1 }; + std::string str; + LogSinkImpl 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]")); +} + } // namespace rtc