-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
For followup after #4611 implementing #4524 is merged.
This PR is implementing the Standard's "Effects equivalent to" wording which is simple and unquestionably correct.
However, blank-line println()
is likely to be a popular function to call, and it appears that it goes through a general codepath that does a lot of work:
Lines 97 to 117 in 0515a05
template <class... _Types> | |
void _Print_impl( | |
const _Add_newline _Add_nl, FILE* const _Stream, const format_string<_Types...> _Fmt, _Types&&... _Args) { | |
constexpr bool _Has_format_args = sizeof...(_Types) > 0; | |
if constexpr (_Has_format_args) { | |
if constexpr (_STD _Is_ordinary_literal_encoding_utf8()) { | |
_STD _Vprint_unicode_impl(_Add_nl, _Stream, _Fmt.get(), _STD make_format_args(_Args...)); | |
} else { | |
_STD _Vprint_nonunicode_impl(_Add_nl, _Stream, _Fmt.get(), _STD make_format_args(_Args...)); | |
} | |
} else { | |
const string _Unescaped_str{_Unescape_braces(_Add_nl, _Fmt.get())}; | |
if constexpr (_STD _Is_ordinary_literal_encoding_utf8()) { | |
_STD _Print_noformat_unicode(_Stream, _Unescaped_str); | |
} else { | |
_STD _Print_noformat_nonunicode(_Stream, _Unescaped_str); | |
} | |
} | |
} |
The optimizer is unlikely to see all the way through this.
From a brief glance, it appears that we could provide the newline as a string_view
, bypassing the construction of a string _Unescaped_str
:
Lines 111 to 115 in 0515a05
if constexpr (_STD _Is_ordinary_literal_encoding_utf8()) { | |
_STD _Print_noformat_unicode(_Stream, _Unescaped_str); | |
} else { | |
_STD _Print_noformat_nonunicode(_Stream, _Unescaped_str); | |
} |
However, it is unclear to me whether we could further optimize this (without spending tons of complicated code). In particular, because we know that "\n"
doesn't contain any exotic characters, could we simply call _Print_noformat_nonunicode
?
For <ostream>
, I believe that less thought is necessary:
Lines 1246 to 1263 in 0515a05
template <class... _Types> | |
void _Print_impl(const _Add_newline _Add_nl, ostream& _Ostr, const format_string<_Types...> _Fmt, _Types&&... _Args) { | |
constexpr bool _Has_format_args = sizeof...(_Types) > 0; | |
// This is intentionally kept outside of the try/catch block in _Print_noformat_*() | |
// (see N4950 [ostream.formatted.print]/3.2). | |
if constexpr (_Has_format_args) { | |
if constexpr (_STD _Is_ordinary_literal_encoding_utf8()) { | |
_STD _Vprint_unicode_impl(_Add_nl, _Ostr, _Fmt.get(), _STD make_format_args(_Args...)); | |
} else { | |
_STD _Vprint_nonunicode_impl(_Add_nl, _Ostr, _Fmt.get(), _STD make_format_args(_Args...)); | |
} | |
} else { | |
const string _Unescaped_str{_Unescape_braces(_Add_nl, _Fmt.get())}; | |
_STD _Print_noformat(_Ostr, _Unescaped_str); | |
} | |
} |
_STD _Print_noformat(_Ostr, _Unescaped_str)
eventually switches between Unicode and non-Unicode, but it has to construct ostream::sentry
machinery first, so it wouldn't be worth digging any deeper.