-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
P2093R14: Formatted Output #3337
Conversation
Updated the fork to the current main.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
This comment was marked as resolved.
…atching what `test_invalid_code_points_console()` does.
I've pushed one more round of changes:
|
I'm speculatively mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed. |
I had to push a commit to fix the compiler's internal "objsize" test, that verifies that including most STL headers doesn't emit object code. This templates the functions being added to |
Co-authored-by: S. B. Tam <cpplearner@outlook.com>
I pushed 3 additional commits to fix the simple but major bug that @cpplearner noticed (thanks again! 😻), added test coverage for empty strings and newlines, and improved the test to avoid leaving temp files behind. |
Thanks for implementing this major C++23 feature! 😻 📜 🎉 |
This PR contains the complete implementation of P2093R14, along with the changes proposed in P2539R3. If merged, it should also close #2916.
Added Files
Some files were added to implement this PR. These may require internal changes to the MSVC and/or Visual Studio which are outside of my control. The added files are as follows:
<print>
: This is the public header described in P2093R14 containing theFILE*
overloads ofstd::print()
et al..<__msvc_filebuf.hpp>
: This is a private, non-core header which contains the definition forstd::basic_filebuf
, which was initially located in<fstream>
. This was necessary in order to define thestd::ostream&
overloads ofstd::print()
et al. within<ostream>
; otherwise, there would be a header circular dependency (<ostream>
-><fstream>
-><istream>
-><ostream>
-> ...).<__msvc_print.hpp>
: This is a private, core header which declares the C API exposing the functionality for printing to Unicode consoles as described in P2093R14.<__msvc_unicode_iterators.hpp>
: This is a private, non-core header which contains the definitions for various Unicode string parsing iterators which were initially located in<format>
. The motivation behind this was to enable large strings to be broken down into grapheme clusters so that calls toWriteConsoleW()
don't result in bad output.src\print.cpp
: This implements the C API declared in<__msvc_print.hpp>
.Implementation Notes
I'm not particularly proud of the current method for checking if
std::ostream
instances refer to Unicode consoles. The proposed implementation uses adynamic_cast
to try to convert thestd::streambuf
of thestd::ostream
instance to astd::filebuf
, and then extracts itsFILE*
if successful. I'm open to suggestions as to how this could be improved. The main difficulty is coming up with a solution which doesn't break ABI. (This is also the method taken by the fmt library.)As a result of the aforementioned implementation detail, the
std::ostream&
overloads ofstd::print()
et al. are currently deleted if RTTI is disabled. (The versions which take aFILE*
instead are still available in that case.)Some optimizations were done to improve code generation in common scenarios:
std::println()
, rather than making a secondstd::vformat()
call as is proposed in the standard, a newline character is manually added to thestd::string
generated by the first call tostd::vformat()
usingstd::basic_string::operator+()
.std::vformat()
is ever actually made. Instead, the providedstd::format_string
itself is parsed to manually remove escaped braces (i.e.,{{
and}}
), and the generated string is what gets printed. This case is checked at compile time by examining thesizeof...
the formatting arguments template parameter pack.Finally, this PR is currently marked as a draft until test cases are added.As always, let me know if you have any questions.