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..54f65496cf 100644 --- a/rtc_base/logging_unittest.cc +++ b/rtc_base/logging_unittest.cc @@ -368,4 +368,18 @@ 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]")); + LogMessage::RemoveLogToStream(&stream); + stream.Close(); +} + } // namespace rtc