Skip to content

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

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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