From ffcc38e3a317a9cae07915db323dd242b880b208 Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sun, 12 May 2024 15:29:24 +0800 Subject: [PATCH 1/8] Optimize `println()` for `FILE*` --- stl/inc/__msvc_print.hpp | 3 +++ stl/inc/print | 56 +++++++++++++++++++++++++++++++++++++++- stl/src/print.cpp | 18 +++++++++++++ 3 files changed, 76 insertions(+), 1 deletion(-) diff --git a/stl/inc/__msvc_print.hpp b/stl/inc/__msvc_print.hpp index edaedc8f3d..2f9c4963cc 100644 --- a/stl/inc/__msvc_print.hpp +++ b/stl/inc/__msvc_print.hpp @@ -55,6 +55,9 @@ _NODISCARD _Success_(return == __std_win_error::_Success) __std_win_error __stdcall __std_print_to_unicode_console(_In_ __std_unicode_console_handle _Console_handle, _In_reads_(_Str_size) const char* _Str, _In_ size_t _Str_size) noexcept; +_NODISCARD _Success_(return == __std_win_error::_Success) __std_win_error + __stdcall __std_print_newline_only_to_unicode_console(_In_ __std_unicode_console_handle _Console_handle) noexcept; + } // extern "C" _STD_BEGIN diff --git a/stl/inc/print b/stl/inc/print index 13f12ea046..b7afce38f8 100644 --- a/stl/inc/print +++ b/stl/inc/print @@ -84,6 +84,52 @@ inline void _Print_noformat_unicode(FILE* const _Stream, const string_view _Str) } } +inline void _Print_newline_only_unicode(FILE* const _Stream) { + const __std_unicode_console_retrieval_result _Unicode_console_retrieval_result{ + __std_get_unicode_console_handle_from_file_stream(_Stream)}; + + // See the documentation for __std_unicode_console_retrieval_result to understand why we do this. + bool _Is_unicode_console; + +#pragma warning(push) +#pragma warning(disable : 4061) // enumerator not explicitly handled by switch label + switch (_Unicode_console_retrieval_result._Error) { + case __std_win_error::_Success: + _Is_unicode_console = true; + break; + + case __std_win_error::_File_not_found: + _Is_unicode_console = false; + break; + + case __std_win_error::_Not_supported: + [[unlikely]] return; + + default: + [[unlikely]] _STD _Throw_system_error_from_std_win_error(_Unicode_console_retrieval_result._Error); + } +#pragma warning(pop) + + if (_Is_unicode_console) { + const bool _Was_flush_successful = _CSTD fflush(_Stream) == 0; + if (!_Was_flush_successful) [[unlikely]] { + _Throw_system_error(static_cast(errno)); + } + + const __std_win_error _Console_print_result = + __std_print_newline_only_to_unicode_console(_Unicode_console_retrieval_result._Console_handle); + if (_Console_print_result != __std_win_error::_Success) [[unlikely]] { + _STD _Throw_system_error_from_std_win_error(_Console_print_result); + } + } else { + const bool _Was_write_successful = _CSTD fputc('\n', _Stream) == '\n'; + + if (!_Was_write_successful) [[unlikely]] { + _Throw_system_error(static_cast(errno)); + } + } +} + inline void _Vprint_unicode_impl( const _Add_newline _Add_nl, FILE* const _Stream, const string_view _Fmt_str, const format_args _Fmt_args) { string _Output_str = _STD vformat(_Fmt_str, _Fmt_args); @@ -133,7 +179,15 @@ void println(FILE* const _Stream, const format_string<_Types...> _Fmt, _Types&&. _EXPORT_STD template // improves throughput, see GH-2329 void println(FILE* _Stream) { - _STD print(_Stream, "\n"); + if constexpr (_STD _Is_ordinary_literal_encoding_utf8()) { + _STD _Print_newline_only_unicode(_Stream); + } else { + const bool _Was_write_successful = _CSTD fputc('\n', _Stream) == '\n'; + + if (!_Was_write_successful) [[unlikely]] { + _Throw_system_error(static_cast(errno)); + } + } } _EXPORT_STD template // improves throughput, see GH-2329 diff --git a/stl/src/print.cpp b/stl/src/print.cpp index fcd7d263e3..1e235717c5 100644 --- a/stl/src/print.cpp +++ b/stl/src/print.cpp @@ -266,4 +266,22 @@ extern "C" { } } +[[nodiscard]] _Success_(return == __std_win_error::_Success) __std_win_error + __stdcall __std_print_newline_only_to_unicode_console( + _In_ const __std_unicode_console_handle _Console_handle) noexcept { + if (_Console_handle == __std_unicode_console_handle::_Invalid) [[unlikely]] { + return __std_win_error::_Invalid_parameter; + } + + const auto _Actual_console_handle = reinterpret_cast(_Console_handle); + + const BOOL _Write_result = WriteConsoleW(_Actual_console_handle, L"\n", static_cast(1), nullptr, nullptr); + + if (!_Write_result) [[unlikely]] { + return static_cast<__std_win_error>(GetLastError()); + } + + return __std_win_error::_Success; +} + } // extern "C" From 3fdadd23bf1b510446ac068f27522f90750ec74a Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sun, 12 May 2024 15:56:24 +0800 Subject: [PATCH 2/8] Optimize `println()` for `ostream` --- stl/inc/__msvc_filebuf.hpp | 3 ++ stl/inc/ostream | 103 ++++++++++++++++++++++++++++++++++++- 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/stl/inc/__msvc_filebuf.hpp b/stl/inc/__msvc_filebuf.hpp index 4d8e76dbc1..ed1438aacf 100644 --- a/stl/inc/__msvc_filebuf.hpp +++ b/stl/inc/__msvc_filebuf.hpp @@ -386,6 +386,9 @@ class basic_filebuf : public basic_streambuf<_Elem, _Traits> { // stream buffer #if _HAS_CXX23 && defined(_CPPRTTI) template friend ios_base::iostate _Print_noformat_unicode(ostream&, string_view); + + template + friend ios_base::iostate _Print_newline_only_unicode(ostream&); #endif protected: diff --git a/stl/inc/ostream b/stl/inc/ostream index b682a8b68b..98dbaf43dd 100644 --- a/stl/inc/ostream +++ b/stl/inc/ostream @@ -1111,6 +1111,24 @@ ios_base::iostate _Print_noformat_nonunicode(ostream& _Ostr, const string_view _ return _State; } +template +ios_base::iostate _Print_newline_only_nonunicode(ostream& _Ostr) { + // *LOCKED* + // + // This function is called from a context in which an ostream::sentry has been + // constructed. + ios_base::iostate _State = ios_base::goodbit; + + _TRY_IO_BEGIN + const auto _Was_insertion_successful = _Ostr.rdbuf()->sputc('\n') == '\n'; + if (!_Was_insertion_successful) [[unlikely]] { + _State |= ios_base::badbit; + } + _CATCH_IO_(ios_base, _Ostr) + + return _State; +} + template void _Vprint_nonunicode_impl( const _Add_newline _Add_nl, ostream& _Ostr, const string_view _Fmt_str, const format_args _Fmt_args) { @@ -1203,6 +1221,76 @@ ios_base::iostate _Print_noformat_unicode(ostream& _Ostr, const string_view _Str return _State; } +template +ios_base::iostate _Print_newline_only_unicode(ostream& _Ostr) { + // *LOCKED* + // + // This function is called from a context in which an ostream::sentry has been + // constructed. + ios_base::iostate _State = ios_base::goodbit; + + // The std::ostream& overload of vprint_unicode() expects you to determine whether the stream refers + // to a unicode console or not based solely on the std::ostream& provided. That class simply doesn't + // provide enough information to know this in every case. The best we can do (without breaking ABI) + // is check if the underlying std::streambuf object of the std::ostream& actually refers to a std::filebuf + // object. This requires the use of a dynamic_cast. (This is also why the std::ostream& overloads of + // std::print() et al. are deleted when RTTI is disabled.) + streambuf* const _Streambuf = _Ostr.rdbuf(); + const auto _Filebuf = dynamic_cast<_Filebuf_type*>(_Streambuf); + + // If we got nullptr, then it probably isn't being used for a unicode console... + if (_Filebuf == nullptr) { + _State |= _STD _Print_newline_only_nonunicode(_Ostr); + return _State; + } + + FILE* const _File_stream = _Filebuf->_Myfile; + const __std_unicode_console_retrieval_result _Unicode_console_retrieval_result{ + __std_get_unicode_console_handle_from_file_stream(_File_stream)}; + + // See the documentation for __std_unicode_console_retrieval_result to understand why we do this. + bool _Is_unicode_console; + +#pragma warning(push) +#pragma warning(disable : 4061) // enumerator not explicitly handled by switch label + switch (_Unicode_console_retrieval_result._Error) { + case __std_win_error::_Success: + _Is_unicode_console = true; + break; + + case __std_win_error::_File_not_found: + _Is_unicode_console = false; + break; + + case __std_win_error::_Not_supported: + [[unlikely]] return _State; + + default: + [[unlikely]] return ios_base::failbit; + } +#pragma warning(pop) + + if (_Is_unicode_console) { + _TRY_IO_BEGIN + const bool _Was_flush_successful = _Ostr.rdbuf()->pubsync() != -1; + if (!_Was_flush_successful) [[unlikely]] { + _State |= ios_base::badbit; + return _State; + } + + const __std_win_error _Unicode_console_print_result = + __std_print_newline_only_to_unicode_console(_Unicode_console_retrieval_result._Console_handle); + if (_Unicode_console_print_result != __std_win_error::_Success) [[unlikely]] { + _State |= ios_base::badbit; + } + _CATCH_IO_(ios_base, _Ostr) + } else { + _State |= _STD _Print_newline_only_nonunicode(_Ostr); + } + + return _State; +} + template void _Vprint_unicode_impl( const _Add_newline _Add_nl, ostream& _Ostr, const string_view _Fmt_str, const format_args _Fmt_args) { @@ -1274,7 +1362,20 @@ void println(ostream& _Ostr, const format_string<_Types...> _Fmt, _Types&&... _A _EXPORT_STD template // improves throughput, see GH-2329 void println(ostream& _Ostr) { - _STD print(_Ostr, "\n"); + const ostream::sentry _Ok(_Ostr); + ios_base::iostate _State = ios_base::goodbit; + + if (!_Ok) [[unlikely]] { + _State |= ios_base::badbit; + } else [[likely]] { + if constexpr (_STD _Is_ordinary_literal_encoding_utf8()) { + _State |= _STD _Print_newline_only_unicode(_Ostr); + } else { + _State |= _STD _Print_newline_only_nonunicode(_Ostr); + } + } + + _Ostr.setstate(_State); } _EXPORT_STD template // improves throughput, see GH-2329 From 25bf26abe0f169f05d8aa13c5b3bf3e081a00900 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 22 Oct 2024 07:09:06 -0700 Subject: [PATCH 3/8] `auto` => `bool` for `_Was_insertion_successful` --- stl/inc/ostream | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/ostream b/stl/inc/ostream index 632a47b1fe..3d3d549fdd 100644 --- a/stl/inc/ostream +++ b/stl/inc/ostream @@ -104,7 +104,7 @@ ios_base::iostate _Print_newline_only_nonunicode(ostream& _Ostr) { ios_base::iostate _State = ios_base::goodbit; _TRY_IO_BEGIN - const auto _Was_insertion_successful = _Ostr.rdbuf()->sputc('\n') == '\n'; + const bool _Was_insertion_successful = _Ostr.rdbuf()->sputc('\n') == '\n'; if (!_Was_insertion_successful) [[unlikely]] { _State |= ios_base::badbit; } From 7c15a6227a943c2c9b20889b0731c83e9a0dfce1 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 22 Oct 2024 07:14:26 -0700 Subject: [PATCH 4/8] Add preprocessor comment to growing region. --- stl/inc/__msvc_filebuf.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/inc/__msvc_filebuf.hpp b/stl/inc/__msvc_filebuf.hpp index ed1438aacf..c80418deb0 100644 --- a/stl/inc/__msvc_filebuf.hpp +++ b/stl/inc/__msvc_filebuf.hpp @@ -389,7 +389,7 @@ class basic_filebuf : public basic_streambuf<_Elem, _Traits> { // stream buffer template friend ios_base::iostate _Print_newline_only_unicode(ostream&); -#endif +#endif // ^^^ _HAS_CXX23 && defined(_CPPRTTI) ^^^ protected: int_type __CLR_OR_THIS_CALL overflow(int_type _Meta = _Traits::eof()) override { // put an element to stream From 47713f57d1136abd515791be8eacf7c38d0a29fc Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 22 Oct 2024 07:21:06 -0700 Subject: [PATCH 5/8] Drop unnecessary `static_cast`. --- stl/src/print.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/src/print.cpp b/stl/src/print.cpp index 0626e3b468..77c3147867 100644 --- a/stl/src/print.cpp +++ b/stl/src/print.cpp @@ -306,7 +306,7 @@ extern "C" { const auto _Actual_console_handle = reinterpret_cast(_Console_handle); - const BOOL _Write_result = WriteConsoleW(_Actual_console_handle, L"\n", static_cast(1), nullptr, nullptr); + const BOOL _Write_result = WriteConsoleW(_Actual_console_handle, L"\n", 1, nullptr, nullptr); if (!_Write_result) [[unlikely]] { return static_cast<__std_win_error>(GetLastError()); From b4fced821d2173f5f68774de2c62469273d9c0c2 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 22 Oct 2024 07:41:31 -0700 Subject: [PATCH 6/8] Use `_Do_on_maybe_unicode_console` for `FILE*` to avoid code duplication. --- stl/inc/print | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) diff --git a/stl/inc/print b/stl/inc/print index cfbdd3a3fd..4c8263c372 100644 --- a/stl/inc/print +++ b/stl/inc/print @@ -193,49 +193,27 @@ inline void _Vprint_unicode_noformat_impl(FILE* const _Stream, const string_view } inline void _Print_newline_only_unicode(FILE* const _Stream) { - const __std_unicode_console_retrieval_result _Unicode_console_retrieval_result{ - __std_get_unicode_console_handle_from_file_stream(_Stream)}; - - // See the documentation for __std_unicode_console_retrieval_result to understand why we do this. - bool _Is_unicode_console; - -#pragma warning(push) -#pragma warning(disable : 4061) // enumerator not explicitly handled by switch label - switch (_Unicode_console_retrieval_result._Error) { - case __std_win_error::_Success: - _Is_unicode_console = true; - break; - - case __std_win_error::_File_not_found: - _Is_unicode_console = false; - break; - - case __std_win_error::_Not_supported: - [[unlikely]] return; - - default: - [[unlikely]] _STD _Throw_system_error_from_std_win_error(_Unicode_console_retrieval_result._Error); - } -#pragma warning(pop) - - if (_Is_unicode_console) { + const auto _Unicode_console = [&](const __std_unicode_console_handle _Console_handle) { const bool _Was_flush_successful = _CSTD fflush(_Stream) == 0; if (!_Was_flush_successful) [[unlikely]] { _Throw_system_error(static_cast(errno)); } - const __std_win_error _Console_print_result = - __std_print_newline_only_to_unicode_console(_Unicode_console_retrieval_result._Console_handle); + const __std_win_error _Console_print_result = __std_print_newline_only_to_unicode_console(_Console_handle); if (_Console_print_result != __std_win_error::_Success) [[unlikely]] { _STD _Throw_system_error_from_std_win_error(_Console_print_result); } - } else { + }; + + const auto _Fallback = [&] { const bool _Was_write_successful = _CSTD fputc('\n', _Stream) == '\n'; if (!_Was_write_successful) [[unlikely]] { _Throw_system_error(static_cast(errno)); } - } + }; + + _STD _Do_on_maybe_unicode_console(_Stream, _Unicode_console, _Fallback); } // Format to intermediate string buffer, then print to unicode console/file From b7c92b8612c07c966108584434f119fe4cc0e819 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 22 Oct 2024 08:03:25 -0700 Subject: [PATCH 7/8] Extract `_Fputc_newline`. --- stl/inc/print | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/stl/inc/print b/stl/inc/print index 4c8263c372..ccb812ddd5 100644 --- a/stl/inc/print +++ b/stl/inc/print @@ -192,6 +192,14 @@ inline void _Vprint_unicode_noformat_impl(FILE* const _Stream, const string_view _STD _Do_on_maybe_unicode_console(_Stream, _Unicode_console, _Fallback); } +inline void _Fputc_newline(FILE* const _Stream) { + const bool _Was_write_successful = _CSTD fputc('\n', _Stream) == '\n'; + + if (!_Was_write_successful) [[unlikely]] { + _Throw_system_error(static_cast(errno)); + } +} + inline void _Print_newline_only_unicode(FILE* const _Stream) { const auto _Unicode_console = [&](const __std_unicode_console_handle _Console_handle) { const bool _Was_flush_successful = _CSTD fflush(_Stream) == 0; @@ -205,13 +213,7 @@ inline void _Print_newline_only_unicode(FILE* const _Stream) { } }; - const auto _Fallback = [&] { - const bool _Was_write_successful = _CSTD fputc('\n', _Stream) == '\n'; - - if (!_Was_write_successful) [[unlikely]] { - _Throw_system_error(static_cast(errno)); - } - }; + const auto _Fallback = [&] { _STD _Fputc_newline(_Stream); }; _STD _Do_on_maybe_unicode_console(_Stream, _Unicode_console, _Fallback); } @@ -298,11 +300,7 @@ void println(FILE* _Stream) { if constexpr (_STD _Is_ordinary_literal_encoding_utf8()) { _STD _Print_newline_only_unicode(_Stream); } else { - const bool _Was_write_successful = _CSTD fputc('\n', _Stream) == '\n'; - - if (!_Was_write_successful) [[unlikely]] { - _Throw_system_error(static_cast(errno)); - } + _STD _Fputc_newline(_Stream); } } From 4ca5e38a496f38e6a1624107ed70b902ca92f41b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 22 Oct 2024 08:27:56 -0700 Subject: [PATCH 8/8] Extract `_Do_on_maybe_unicode_console` for `ostream& _Ostr`. --- stl/inc/__msvc_filebuf.hpp | 7 +-- stl/inc/ostream | 89 +++++++++----------------------------- 2 files changed, 23 insertions(+), 73 deletions(-) diff --git a/stl/inc/__msvc_filebuf.hpp b/stl/inc/__msvc_filebuf.hpp index c80418deb0..4a219f592e 100644 --- a/stl/inc/__msvc_filebuf.hpp +++ b/stl/inc/__msvc_filebuf.hpp @@ -384,11 +384,8 @@ class basic_filebuf : public basic_streambuf<_Elem, _Traits> { // stream buffer } #if _HAS_CXX23 && defined(_CPPRTTI) - template - friend ios_base::iostate _Print_noformat_unicode(ostream&, string_view); - - template - friend ios_base::iostate _Print_newline_only_unicode(ostream&); + template + friend ios_base::iostate _Do_on_maybe_unicode_console(ostream&, _UnicodeConsoleFn, _FallbackFn); #endif // ^^^ _HAS_CXX23 && defined(_CPPRTTI) ^^^ protected: diff --git a/stl/inc/ostream b/stl/inc/ostream index 3d3d549fdd..3357fd3aad 100644 --- a/stl/inc/ostream +++ b/stl/inc/ostream @@ -135,8 +135,9 @@ void _Vprint_nonunicode_impl( _Ostr.setstate(_State); } -template -ios_base::iostate _Print_noformat_unicode(ostream& _Ostr, const string_view _Str) { +template +ios_base::iostate _Do_on_maybe_unicode_console( + ostream& _Ostr, _UnicodeConsoleFn _Unicode_console_func, _FallbackFn _Fallback_func) { // *LOCKED* // // This function is called from a context in which an ostream::sentry has been @@ -154,7 +155,7 @@ ios_base::iostate _Print_noformat_unicode(ostream& _Ostr, const string_view _Str // If we got nullptr, then it probably isn't being used for a unicode console... if (_Filebuf == nullptr) { - _State |= _STD _Print_noformat_nonunicode(_Ostr, _Str); + _State |= _Fallback_func(); return _State; } @@ -193,86 +194,38 @@ ios_base::iostate _Print_noformat_unicode(ostream& _Ostr, const string_view _Str } const __std_win_error _Unicode_console_print_result = - __std_print_to_unicode_console(_Unicode_console_retrieval_result._Console_handle, _Str.data(), _Str.size()); + _Unicode_console_func(_Unicode_console_retrieval_result._Console_handle); if (_Unicode_console_print_result != __std_win_error::_Success) [[unlikely]] { _State |= ios_base::badbit; } _CATCH_IO_(ios_base, _Ostr) } else { - _State |= _STD _Print_noformat_nonunicode(_Ostr, _Str); + _State |= _Fallback_func(); } return _State; } -template -ios_base::iostate _Print_newline_only_unicode(ostream& _Ostr) { - // *LOCKED* - // - // This function is called from a context in which an ostream::sentry has been - // constructed. - ios_base::iostate _State = ios_base::goodbit; - - // The std::ostream& overload of vprint_unicode() expects you to determine whether the stream refers - // to a unicode console or not based solely on the std::ostream& provided. That class simply doesn't - // provide enough information to know this in every case. The best we can do (without breaking ABI) - // is check if the underlying std::streambuf object of the std::ostream& actually refers to a std::filebuf - // object. This requires the use of a dynamic_cast. (This is also why the std::ostream& overloads of - // std::print() et al. are deleted when RTTI is disabled.) - streambuf* const _Streambuf = _Ostr.rdbuf(); - const auto _Filebuf = dynamic_cast<_Filebuf_type*>(_Streambuf); - - // If we got nullptr, then it probably isn't being used for a unicode console... - if (_Filebuf == nullptr) { - _State |= _STD _Print_newline_only_nonunicode(_Ostr); - return _State; - } - - FILE* const _File_stream = _Filebuf->_Myfile; - const __std_unicode_console_retrieval_result _Unicode_console_retrieval_result{ - __std_get_unicode_console_handle_from_file_stream(_File_stream)}; - - // See the documentation for __std_unicode_console_retrieval_result to understand why we do this. - bool _Is_unicode_console; - -#pragma warning(push) -#pragma warning(disable : 4061) // enumerator not explicitly handled by switch label - switch (_Unicode_console_retrieval_result._Error) { - case __std_win_error::_Success: - _Is_unicode_console = true; - break; - - case __std_win_error::_File_not_found: - _Is_unicode_console = false; - break; +template +ios_base::iostate _Print_noformat_unicode(ostream& _Ostr, const string_view _Str) { + const auto _Unicode_console = [&](const __std_unicode_console_handle _Console_handle) { + return __std_print_to_unicode_console(_Console_handle, _Str.data(), _Str.size()); + }; - case __std_win_error::_Not_supported: - [[unlikely]] return _State; + const auto _Fallback = [&] { return _STD _Print_noformat_nonunicode(_Ostr, _Str); }; - default: - [[unlikely]] return ios_base::failbit; - } -#pragma warning(pop) + return _STD _Do_on_maybe_unicode_console(_Ostr, _Unicode_console, _Fallback); +} - if (_Is_unicode_console) { - _TRY_IO_BEGIN - const bool _Was_flush_successful = _Ostr.rdbuf()->pubsync() != -1; - if (!_Was_flush_successful) [[unlikely]] { - _State |= ios_base::badbit; - return _State; - } +template +ios_base::iostate _Print_newline_only_unicode(ostream& _Ostr) { + const auto _Unicode_console = [](const __std_unicode_console_handle _Console_handle) { + return __std_print_newline_only_to_unicode_console(_Console_handle); + }; - const __std_win_error _Unicode_console_print_result = - __std_print_newline_only_to_unicode_console(_Unicode_console_retrieval_result._Console_handle); - if (_Unicode_console_print_result != __std_win_error::_Success) [[unlikely]] { - _State |= ios_base::badbit; - } - _CATCH_IO_(ios_base, _Ostr) - } else { - _State |= _STD _Print_newline_only_nonunicode(_Ostr); - } + const auto _Fallback = [&] { return _STD _Print_newline_only_nonunicode(_Ostr); }; - return _State; + return _STD _Do_on_maybe_unicode_console(_Ostr, _Unicode_console, _Fallback); } template