diff options
author | 2022-11-02 15:27:54 -0700 | |
---|---|---|
committer | 2022-11-02 15:28:46 -0700 | |
commit | e6044634dd7caec2d79a13aecc9e765023768757 (patch) | |
tree | 3ffe2c00f4b5e49da4f4e7d9e50c64999f318408 /absl/log/internal/log_message.h | |
parent | 1649c037c556bdaca7241bc0113275506bdb9638 (diff) |
Support logging of user-defined types that implement `AbslStringify()`
If a user-defined type has `AbslStringify()` defined, it will always be used for logging over `operator<<`.
`HasAbslStringify` now uses the empty class `UnimplementedSink` for its checks instead of `StringifySink` in order to make it work in cases involving other sinks.
PiperOrigin-RevId: 485710377
Change-Id: Ibdd916151c7abc3269c35fbe79b772867f3d25e1
Diffstat (limited to 'absl/log/internal/log_message.h')
-rw-r--r-- | absl/log/internal/log_message.h | 48 |
1 files changed, 45 insertions, 3 deletions
diff --git a/absl/log/internal/log_message.h b/absl/log/internal/log_message.h index 37a267c0..992bb630 100644 --- a/absl/log/internal/log_message.h +++ b/absl/log/internal/log_message.h @@ -41,6 +41,7 @@ #include "absl/log/internal/nullguard.h" #include "absl/log/log_entry.h" #include "absl/log/log_sink.h" +#include "absl/strings/internal/has_absl_stringify.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" @@ -153,8 +154,17 @@ class LogMessage { template <int SIZE> LogMessage& operator<<(char (&buf)[SIZE]) ABSL_ATTRIBUTE_NOINLINE; - // Default: uses `ostream` logging to convert `v` to a string. - template <typename T> + // Types that support `AbslStringify()` are serialized that way. + template <typename T, + typename std::enable_if< + strings_internal::HasAbslStringify<T>::value, int>::type = 0> + LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE; + + // Types that don't support `AbslStringify()` but do support streaming into a + // `std::ostream&` are serialized that way. + template <typename T, + typename std::enable_if< + !strings_internal::HasAbslStringify<T>::value, int>::type = 0> LogMessage& operator<<(const T& v) ABSL_ATTRIBUTE_NOINLINE; // Note: We explicitly do not support `operator<<` for non-const references @@ -205,12 +215,44 @@ class LogMessage { std::ostream stream_; }; +// Helper class so that `AbslStringify()` can modify the LogMessage. +class StringifySink final { + public: + explicit StringifySink(LogMessage& message) : message_(message) {} + + void Append(size_t count, char ch) { message_ << std::string(count, ch); } + + void Append(absl::string_view v) { message_ << v; } + + // For types that implement `AbslStringify` using `absl::Format()`. + friend void AbslFormatFlush(StringifySink* sink, absl::string_view v) { + sink->Append(v); + } + + private: + LogMessage& message_; +}; + +// Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE` +template <typename T, + typename std::enable_if<strings_internal::HasAbslStringify<T>::value, + int>::type> +LogMessage& LogMessage::operator<<(const T& v) { + StringifySink sink(*this); + // Replace with public API. + AbslStringify(sink, v); + return *this; +} + // Note: the following is declared `ABSL_ATTRIBUTE_NOINLINE` -template <typename T> +template <typename T, + typename std::enable_if<!strings_internal::HasAbslStringify<T>::value, + int>::type> LogMessage& LogMessage::operator<<(const T& v) { stream_ << log_internal::NullGuard<T>().Guard(v); return *this; } + inline LogMessage& LogMessage::operator<<( std::ostream& (*m)(std::ostream& os)) { stream_ << m; |