Reputation: 2603
This answer mentions how you can include <fmt/ostream.h>
to have ostream-printable types recognized by {fmt}. I noticed that it doesn't work when the type is in a namespace:
#include <fmt/format.h>
#include <fmt/ostream.h>
namespace foo {
struct A {};
}
std::ostream& operator<<(std::ostream& os, const foo::A& a)
{
return os << "A!";
}
int main()
{
fmt::print("{}\n", foo::A{});
}
This will result in the old error (before including #include <fmt/ostream.h>
) for a type without a namespace again:
fmt/core.h:1422:3: error: static_assert failed due to requirement 'fmt::formattable<foo::A>()' "Cannot format an argument. To make type T formattable provide a formatter<T> specialization: https://fmt.dev/latest/api.html#udt"
static_assert(
^
fmt/core.h:1438:10: note: in instantiation of function template specialization 'fmt::detail::check<foo::A>' requested here
return check<T>(arg_mapper<Context>().map(val));
^
fmt/core.h:1587:23: note: in instantiation of function template specialization 'fmt::detail::make_arg<true, fmt::basic_format_context<fmt::detail::buffer_appender<char>, char>, fmt::detail::type::custom_type, foo::A, 0>' requested here
data_{detail::make_arg<
^
fmt/core.h:1626:10: note: in instantiation of member function 'fmt::format_arg_store<fmt::basic_format_context<fmt::detail::buffer_appender<char>, char>, foo::A>::format_arg_store' requested here
return {args...};
^
fmt/core.h:2114:28: note: in instantiation of function template specialization 'fmt::make_args_checked<foo::A, char [4], char>' requested here
const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
^
main.cpp:15:8: note: in instantiation of function template specialization 'fmt::print<char [4], foo::A, char>' requested here
fmt::print("{}\n", foo::A{});
^
Is there a way to make it work without implementing formatter<foo::A>
?
Upvotes: 1
Views: 1062
Reputation: 576
In fmt v8 the code valid, but invalid in fmt v9.
The C++ 20 standard do not support to overload to std::ostream<<
API v8 https://fmt.dev/8.1.1/api.html#ostream-api
API latest(v9) https://fmt.dev/latest/api.html#ostream-api
But why C++std not to format by std::ostream<<
?
Upvotes: 1
Reputation: 2973
By argument-dependent lookup, it's required to put the operator<<
definition inside the foo
namespace:
#include <fmt/format.h>
#include <fmt/ostream.h>
namespace foo {
struct A {};
std::ostream& operator<<(std::ostream& os, const A& a)
{
return os << "A!";
}
} // namespace foo
int main()
{
fmt::print("{}\n", foo::A{});
}
Upvotes: 8