I have a header that defines all {fmt} formatters for my custom types.
To improve compile times, I wanted to reduce the dependencies of this custom formatter header, and decided to define all formatters as external templates, where the implementation is put in a .cpp
, with the declarations in the header file as follows:
template<>
struct formatter<MyType> : formatter<std::string>
{
auto format(const MyType& t, format_context& ctx);
};
extern template struct formatter<MyType>;
...and the definitions in the .cpp
file:
auto formatter<MyType>::format(const MyType& t, format_context& ctx)
{
return format_to(ctx.out, "MyType: {}", ...);
}
The main advantage is that the header file becomes much less heavy, all custom types can be forward declared and I no longer include the world just to have custom formatting of a single type within some translation unit.
However, most of the examples on implementing custom formatters with {fmt} define the format()
function as a function templated on the format_context
type:
template<typename FormatContext>
auto format(const MyType& t, FormatContext& ctx);
This does not really work with external templates since I would need to declare format()
for all possible types of FormatContext
up front. This is error prone. For now, only using fmt::format_context
works and the compiler will tell me when it no longer suffices.
I would like to know what I lose by not having a format function templated on the FormatContext
type. In what situations is fmt::format_context
not sufficient? Is there a better way to define these custom type formatters without having to put the complete implementation in header files? I was thinking about going the std::ostream
route, and then simply including <fmt/ostream.h>
whenever I would want to format my types with {fmt}, but it partially defeats the purpose of using {fmt} in the first place.
what I lose by not having a format function templatized on the FormatContext type?
You'll lose the ability to format through an output iterator.
Previously this would mean that you won't be able to use
format_to[_n]
. However in the current master
this limitation has
been removed and both format_to
and format_to_n
work with
format_context
. Now only format string
compilation may require
custom output iterators.