I’m looking into providing ostream operators for some math classes (matrix, vector, etc.) A friend has noted that the gcc standard library implementation of the ostream operator for std::complex includes the internal use of a string stream to format the output before passing it to the actual ostream:
/// Insertion operator for complex values.
template<typename _Tp, typename _CharT, class _Traits>
basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x)
{
basic_ostringstream<_CharT, _Traits> __s;
__s.flags(__os.flags());
__s.imbue(__os.getloc());
__s.precision(__os.precision());
__s << '(' << __x.real() << ',' << __x.imag() << ')';
return __os << __s.str();
}
This pattern is visible in boost as well. We’re trying to determine if this is a pattern worth following. There have been concerns that it involves including an extra header for the string stream and there are additional heap allocations required within the string stream which could potentially be avoided.
Most reasonably it has been suggested that if the client requires that functionality, then they can create the string stream and do the pre-pass themselves.
Can anyone help me understand why this would be considered good practice and whether I should be adopting it?
Consider what happens if you set an output width on the ostream, then write a std::complex to it – you don’t want the width to only affect the first output operation (i.e. the
'('character)This should print
"(0,1) "not"( 0,1)"By forming the entire output as a single string then writing it out the output honours the field width and other formatting flags set on the stream.