-
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
<format>
: Make formatter
cast the argument to the correct type before constructing basic_format_arg
#3723
Conversation
This seems to be the Standard's intended behavior. [format.string.std]/21 says that "The available integer presentation types for integral types other than Am I missing something? |
At the weekly maintainer meeting, @barcharcraz agreed with @CaseyCarter here - this may seem weird but it appears that the Standard mandates this behavior. |
That's my first thought as well, but that makes
|
Might be some wording missing that says that char is converted to Char (the intended behavior). Formatting char as a number is, of course, wrong. If this is the case please open an LWG issue. |
Actually the wording is there: https://eel.is/c++draft/format#arg-6.2. So the only thing that potentially needs clarification is connection to this nice table https://eel.is/c++draft/format.string.std#tab:format.type.char. |
That table appears to apply only to charT (wchar_t here), but the wording for basic_format_arg's constructor may be sufficient. |
if the other two implementations produce 'a' then I wouldn't be super opposed to just pre-emptively implementing that pending the resolution of whatever LWG issue addresses the wording, however I'm not sure I love the approach in this PR, I would strongly prefer keeping all the handling of these conversions in the basic_format_arg constructor, since that's where it's depicted in the standard and because that overload set is complicated and I'd like it in one place as much as possible. |
I would love to drop This PR makes |
Isn't it #2320 related? |
The complicated overload set is unified to a single contructor by LWG-3631. Since the constructor (formerly contructors) is exposition-only, I'd like to keep the internal constructors of Otherwise, we might need to write something like the following to initialize the specified variant member. // ...
template <class _Ty>
explicit basic_format_arg(_Ty& _Val) noexcept
requires (_Dispatched<_Ty> == _Basic_format_arg_type::_Int_type)
: _Active_state(_Basic_format_arg_type::_Int_type), _Int_state(_Val) {}
template <class _Ty>
explicit basic_format_arg(_Ty& _Val) noexcept
requires (_Dispatched<_Ty> == _Basic_format_arg_type::_UInt_type)
: _Active_state(_Basic_format_arg_type::_UInt_type), _UInt_state(_Val) {}
// ... |
I agree, that's the reason why libc++ gives L"a" as result. |
Aha! I've forgotten again that "format arg" in [format.string.std] means something like "the content of the |
I'm speculatively mirroring this to the MSVC-internal repo - please notify me if any further changes are pushed. |
Sorry for the dumb question. |
Stephan is speculating that someone will perform Final Review on this so we can merge it as part of a single batch merge into the internal repo. Pointing it out in the "notify me of changes" comment serves only to avoid confusion about why we'd be preparing to merge something that isn't in the "Ready to Merge" state. |
FWIW there's a latent merge conflict between this PR and #3726. This might be solved by merging with |
I've pushed a merge with |
Thanks for figuring out the best way to fix this bug! 🛠️ 🐞 😻 |
Found while testing
formatter<char, wchar_t>
. Overload resolution seems to choosebasic_format_arg(const int _Val)
, causing thechar
value to be formatted as an integer, rather than a character.PR #2768 fixed a similar issue for
long
(where overload resolution was ambiguous), by adding constructors tobasic_format_arg
. We could add another constructor to address this issue, and add yet another constructor to fixformatter<nullptr_t, CharT>
, and still another constructor forbasic_string
with customTraits
. That's not too bad, but kinda duplicates the logic in_Format_arg_traits
. So I choose to just use_Format_arg_traits
.