Skip to content

[libc++] std::format does not compile with formatter specialization of user-defined types. #66466

Open
@memchr

Description

@memchr

When using libc++, clang (trunk 20230914) fails to compile code using std::format with user-defined formatter
specialisation.

Minimal example, flags -std=c++20 -fexperimental-library -stdlib=libc++

#include <iostream>
#include <format>

struct Type {};

template <>
struct std::formatter<Type> : std::formatter<std::string> {
    auto format(Type p, format_context& ctx) const {
        return formatter<string>::format("test", ctx);
    }
};

int main() {
    std::cout << std::format("{}", Type{}) << std::endl;
}
Error
<source>:14:30: error: call to consteval function 'std::basic_format_string<char, Type>::basic_format_string<char[3]>' is not a constant expression
   14 |     std::cout << std::format("{}", Type{}) << std::endl;
      |                              ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_functions.h:268:7: note: non-constexpr function '__throw_format_error' cannot be used in a constant expression
  268 |       std::__throw_format_error("The argument index value is too large for the number of arguments supplied");
      |       ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_functions.h:315:13: note: in call to '__handle_replacement_field<const char *, std::basic_format_parse_context<char>, std::__format::__compile_time_basic_format_context<char>>(&"{}"[1], &"{}"[2], basic_format_parse_context<char>{this->__str_, sizeof...(_Args)}, _Context{__types_.data(), __handles_.data(), sizeof...(_Args)})'
  315 |             __format::__handle_replacement_field(__begin, __end, __parse_ctx, __ctx);
      |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_functions.h:346:5: note: in call to '__vformat_to<std::basic_format_parse_context<char>, std::__format::__compile_time_basic_format_context<char>>(basic_format_parse_context<char>{this->__str_, sizeof...(_Args)}, _Context{__types_.data(), __handles_.data(), sizeof...(_Args)})'
  346 |     __format::__vformat_to(basic_format_parse_context<_CharT>{__str_, sizeof...(_Args)},
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  347 |                            _Context{__types_.data(), __handles_.data(), sizeof...(_Args)});
      |                            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:14:30: note: in call to 'basic_format_string<char[3]>("{}")'
   14 |     std::cout << std::format("{}", Type{}) << std::endl;
      |                              ^~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_error.h:41:1: note: declared here
   41 | __throw_format_error(const char* __s) {
      | ^
In file included from <source>:2:
In file included from /opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/format:176:
In file included from /opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/container_adaptor.h:20:
In file included from /opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/range_default_formatter.h:23:
In file included from /opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/range_formatter.h:23:
In file included from /opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_context.h:18:
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg_store.h:167:17: error: static assertion failed due to requirement '__arg != __arg_t::__none': the supplied type is not formattable
  167 |   static_assert(__arg != __arg_t::__none, "the supplied type is not formattable");
      |                 ^~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg_store.h:210:54: note: in instantiation of function template specialization 'std::__format::__create_format_arg<std::format_context, Type>' requested here
  210 |         basic_format_arg<_Context> __arg = __format::__create_format_arg<_Context>(__args);
      |                                                      ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg_store.h:246:19: note: in instantiation of function template specialization 'std::__format::__create_packed_storage<std::format_context, Type &>' requested here
  246 |         __format::__create_packed_storage(__storage.__types_, __storage.__values_, __args...);
      |                   ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_functions.h:67:10: note: in instantiation of member function 'std::__format_arg_store<std::format_context, Type &>::__format_arg_store' requested here
   67 |   return _VSTD::__format_arg_store<_Context, _Args...>(__args...);
      |          ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__config:784:17: note: expanded from macro '_VSTD'
  784 | #  define _VSTD std
      |                 ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_functions.h:454:45: note: in instantiation of function template specialization 'std::make_format_args<std::format_context, Type &>' requested here
  454 |   return _VSTD::vformat(__fmt.get(), _VSTD::make_format_args(__args...));
      |                                             ^
<source>:14:23: note: in instantiation of function template specialization 'std::format<Type>' requested here
   14 |     std::cout << std::format("{}", Type{}) << std::endl;
      |                       ^
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg_store.h:167:23: note: expression evaluates to '0 != 0'
  167 |   static_assert(__arg != __arg_t::__none, "the supplied type is not formattable");
      |                 ~~~~~~^~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg_store.h:201:12: error: no matching constructor for initialization of 'basic_format_arg<format_context>'
  201 |     return basic_format_arg<_Context>{__arg, __value};
      |            ^                         ~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg.h:252:34: note: candidate constructor not viable: no known conversion from 'Type' to '__basic_format_arg_value<format_context>' for 2nd argument
  252 |   _LIBCPP_HIDE_FROM_ABI explicit basic_format_arg(__format::__arg_t __type,
      |                                  ^
  253 |                                                   __basic_format_arg_value<_Context> __value) noexcept
      |                                                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg.h:223:28: note: candidate constructor (the implicit copy constructor) not viable: requires 1 argument, but 2 were provided
  223 | class _LIBCPP_TEMPLATE_VIS basic_format_arg {
      |                            ^~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg.h:223:28: note: candidate constructor (the implicit move constructor) not viable: requires 1 argument, but 2 were provided
  223 | class _LIBCPP_TEMPLATE_VIS basic_format_arg {
      |                            ^~~~~~~~~~~~~~~~
/opt/compiler-explorer/clang-trunk-20230914/bin/../include/c++/v1/__format/format_arg.h:227:25: note: candidate constructor not viable: requires 0 arguments, but 2 were provided
  227 |   _LIBCPP_HIDE_FROM_ABI basic_format_arg() noexcept
      |                         ^
3 errors generated.
Compiler returned: 1

Metadata

Metadata

Assignees

Labels

formatC++20 std::format or std::print, and anything related to themlibc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.questionA question, not bug report. Check out https://llvm.org/docs/GettingInvolved.html instead!

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions