Skip to content

Commit

Permalink
<format>: Make formatter cast the argument to the correct type be…
Browse files Browse the repository at this point in the history
…fore constructing `basic_format_arg` (#3723)

Co-authored-by: Stephan T. Lavavej <[email protected]>
  • Loading branch information
cpplearner and StephanTLavavej authored May 31, 2023
1 parent a8c4737 commit 6a98456
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 9 deletions.
21 changes: 13 additions & 8 deletions stl/inc/format
Original file line number Diff line number Diff line change
Expand Up @@ -695,10 +695,6 @@ public:
: _Active_state(_Basic_format_arg_type::_Int_type), _Int_state(_Val) {}
explicit basic_format_arg(const unsigned int _Val) noexcept
: _Active_state(_Basic_format_arg_type::_UInt_type), _UInt_state(_Val) {}
explicit basic_format_arg(const long _Val) noexcept
: _Active_state(_Basic_format_arg_type::_Int_type), _Int_state(_Val) {}
explicit basic_format_arg(const unsigned long _Val) noexcept
: _Active_state(_Basic_format_arg_type::_UInt_type), _UInt_state(_Val) {}
explicit basic_format_arg(const long long _Val) noexcept
: _Active_state(_Basic_format_arg_type::_Long_long_type), _Long_long_state(_Val) {}
explicit basic_format_arg(const unsigned long long _Val) noexcept
Expand Down Expand Up @@ -3548,10 +3544,19 @@ struct _Formatter_base {
_FormatCtx.arg(static_cast<size_t>(_Specs._Dynamic_precision_index)));
}

return _STD visit_format_arg(
_Arg_formatter<typename _FormatContext::iterator, _CharT>{
._Ctx = _STD addressof(_FormatCtx), ._Specs = _STD addressof(_Format_specs)},
basic_format_arg<_FormatContext>{_Val});
using _Erased_type = _Format_arg_traits<_FormatContext>::template _Storage_type<_Ty>;

_Arg_formatter<typename _FormatContext::iterator, _CharT> _Visitor{
._Ctx = _STD addressof(_FormatCtx), ._Specs = _STD addressof(_Format_specs)};
#if !_HAS_CXX23
if constexpr (is_same_v<_Erased_type, basic_string_view<_CharT>>) {
return _STD visit_format_arg(
_Visitor, basic_format_arg<_FormatContext>{_Erased_type{_Val.data(), _Val.size()}});
} else
#endif // !_HAS_CXX23
{
return _STD visit_format_arg(_Visitor, basic_format_arg<_FormatContext>{static_cast<_Erased_type>(_Val)});
}
}

private:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ struct std::formatter<custom_formattable_type<T>, charT> : std::formatter<T, cha
}
};

constexpr void test_disabled_formatter_is_disabled() {
constexpr void test_disabled_formatter_is_disabled() { // COMPILE-ONLY
using F = formatter<void, void>;

static_assert(!is_default_constructible_v<F>);
Expand Down Expand Up @@ -184,6 +184,21 @@ void test_custom_formattable_type() {
test_numeric_custom_formattable_type<float, charT>();
test_numeric_custom_formattable_type<double, charT>();
test_numeric_custom_formattable_type<long double, charT>();

test_custom_equiv_with_format<charT, charT>(STR("{}"), charT(' '));
test_custom_equiv_with_format<char, charT>(STR("{}"), ' ');

charT test_str[] = {charT(' '), charT()};
test_custom_equiv_with_format<charT*, charT>(STR("{}"), test_str);
test_custom_equiv_with_format<const charT*, charT>(STR("{}"), test_str);

struct traits : char_traits<charT> {};
test_custom_equiv_with_format<basic_string<charT, traits>, charT>(STR("{}"), test_str);
test_custom_equiv_with_format<basic_string_view<charT, traits>, charT>(STR("{}"), test_str);

test_custom_equiv_with_format<nullptr_t, charT>(STR("{}"), nullptr);
test_custom_equiv_with_format<void*, charT>(STR("{}"), nullptr);
test_custom_equiv_with_format<const void*, charT>(STR("{}"), nullptr);
}

template <class charT>
Expand All @@ -201,6 +216,21 @@ void test_mixed_custom_formattable_type() {
test_numeric_mixed_args_custom_formattable_type<float, charT>();
test_numeric_mixed_args_custom_formattable_type<double, charT>();
test_numeric_mixed_args_custom_formattable_type<long double, charT>();

test_custom_equiv_with_format_mixed<charT, charT>(STR("{}{}"), charT(' '));
test_custom_equiv_with_format_mixed<char, charT>(STR("{}{}"), ' ');

charT test_str[] = {charT(' '), charT()};
test_custom_equiv_with_format_mixed<charT*, charT>(STR("{}{}"), test_str);
test_custom_equiv_with_format_mixed<const charT*, charT>(STR("{}{}"), test_str);

struct traits : char_traits<charT> {};
test_custom_equiv_with_format_mixed<basic_string<charT, traits>, charT>(STR("{}{}"), test_str);
test_custom_equiv_with_format_mixed<basic_string_view<charT, traits>, charT>(STR("{}{}"), test_str);

test_custom_equiv_with_format_mixed<nullptr_t, charT>(STR("{}{}"), nullptr);
test_custom_equiv_with_format_mixed<void*, charT>(STR("{}{}"), nullptr);
test_custom_equiv_with_format_mixed<const void*, charT>(STR("{}{}"), nullptr);
}

int main() {
Expand Down

0 comments on commit 6a98456

Please sign in to comment.