Every big tech company (like FAANG) has its own implementation of std::string
and/or a string utils library.
All over in the code, if you want to send a slightly changed string to the output stream (an output stream is an object with the <<
operator, like std::cout
, std::stringstream
), there is a new string created:
1
log << "Value is " << valueStr.Quote();
The Quote
method here creates a new string with quotes "
on the left and the right end of the string. We meet this code everywhere and it harms performanceโฑ, but this looks better than printing ugly "\""
.
Letโs try to create a โflagโ for performance optimal string printing, just like std::boolalpha. We want to write like this:
1
log << "Value is " << quote << valueStr;
so it is the equivalent of this:
1
log << "Value is " << '"' << valueStr << '"';
How to do this? Letโs say this expression: ((stream object) << quote)
returns a TQuoteWrapper
objects, and this expression: ((a TQuoteWrapper object) << str)
returns the original stream object with str
written there.
We can work with any stream object. The quote
object means nothing and serves only to make possible the expressions above.
1
2
3
4
5
6
inline constexpr struct quote_t{} quote;
template<typename TStream>
auto operator<<(TStream& stream, quote_t) {
return TQuoteWrapper{stream};
}
The TQuoteWrapper
class has the <<
operator:
1
2
3
4
template<typename TArg>
TStream& operator<<(TArg&& arg) {
return Stream_ << '"' << std::forward<TArg>(arg) << '"';
}
Link to godbolt with this class and examples.
Also we can implement that the TQuoteWrapper
escapes string chars (for example, replacing \"
to \\\"
). Link to godbolt to that implementation.
Another approach to performance-friendly string streaming is in the abseil library - Writing to Stream. There we pass a โlightโ object to the stream:
1
std::cout << absl::StreamFormat("\"%s\"", valueStr);
But there is a constraint - you canโt atritrarily customize the string (like escaping its chars).