Skip to content

Formatting a std::string with "{:x}" doesn't throw a fmt::format_error with version 8.0.0 #2402

@neo1973

Description

@neo1973

This code throws an exception when compiled with fmt 7.1.3 but not with 8.0.0:

#include <fmt/format.h>
#include <string>

int main() {
    fmt::print( "{:x}", std::string( "test" ) );
}

Was this change in behaviour intentionally or is this a regression?

When compiling in C++20 mode the code creates a compiler error with 8.0.0 which is inconsistent compared to the runtime behaviour:

In file included from /opt/compiler-explorer/libs/fmt/trunk/include/fmt/format.h:44,
                 from <source>:2:
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h: In function 'int main()':
<source>:7:15:   in 'constexpr' expansion of 'fmt::v8::basic_format_string<char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >("{:x}")'
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:2857:40:   in 'constexpr' expansion of 'fmt::v8::detail::parse_format_string<true, char, fmt::v8::detail::format_string_checker<char, fmt::v8::detail::error_handler, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > > >(((fmt::v8::basic_format_string<char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)this)->fmt::v8::basic_format_string<char, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::str_, fmt::v8::detail::format_string_checker<char, fmt::v8::detail::error_handler, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(fmt::v8::basic_string_view<char>(((const char*)s)), (fmt::v8::detail::error_handler(), fmt::v8::detail::error_handler())))'
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:2408:44:   in 'constexpr' expansion of 'fmt::v8::detail::parse_replacement_field<char, fmt::v8::detail::format_string_checker<char, fmt::v8::detail::error_handler, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&>((p + -1), end, (* & handler))'
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:2383:38:   in 'constexpr' expansion of '(& handler)->fmt::v8::detail::format_string_checker<char, fmt::v8::detail::error_handler, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::on_format_specs(adapter.fmt::v8::detail::parse_replacement_field<char, fmt::v8::detail::format_string_checker<char, fmt::v8::detail::error_handler, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&>(const char*, const char*, fmt::v8::detail::format_string_checker<char, fmt::v8::detail::error_handler, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >&)::id_adapter::arg_id, (begin + 1), end)'
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:2726:51:   in 'constexpr' expansion of '((fmt::v8::detail::format_string_checker<char, fmt::v8::detail::error_handler, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)this)->fmt::v8::detail::format_string_checker<char, fmt::v8::detail::error_handler, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::parse_funcs_[id](((fmt::v8::detail::format_string_checker<char, fmt::v8::detail::error_handler, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >*)this)->fmt::v8::detail::format_string_checker<char, fmt::v8::detail::error_handler, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >::context_)'
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:2457:17:   in 'constexpr' expansion of 'f.fmt::v8::formatter<fmt::v8::basic_string_view<char>, char, void>::parse<fmt::v8::detail::compile_parse_context<char, fmt::v8::detail::error_handler> >((* & ctx))'
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:2819:37:   in 'constexpr' expansion of 'fmt::v8::detail::check_string_type_spec<char, fmt::v8::detail::error_handler&>(((int)((fmt::v8::formatter<fmt::v8::basic_string_view<char>, char, void>*)this)->fmt::v8::formatter<fmt::v8::basic_string_view<char>, char, void>::specs_.fmt::v8::detail::dynamic_format_specs<char>::<anonymous>.fmt::v8::basic_format_specs<char>::type), eh)'
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/core.h:2594:44: error: call to non-'constexpr' function 'void fmt::v8::detail::error_handler::on_error(const char*)'
 2594 |   if (spec != 0 && spec != 's') eh.on_error("invalid type specifier");
      |                                 ~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /opt/compiler-explorer/libs/fmt/trunk/include/fmt/format.h:2825,
                 from <source>:2:
/opt/compiler-explorer/libs/fmt/trunk/include/fmt/format-inl.h:2553:15: note: 'void fmt::v8::detail::error_handler::on_error(const char*)' declared here
 2553 | FMT_FUNC void detail::error_handler::on_error(const char* message) {
      |               ^~~~~~

Godbolt

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions