我有一个头文件,用于定义我自己类型的所有{fmt}格式化程序。
为了提高编译时间,我希望减少这个自定义格式化程序头文件的依赖关系,并决定将所有格式化程序定义为外部模板,其中实现放在.cpp
中,在头文件中声明如下:
template<>
struct formatter<MyType> : formatter<std::string>
{
auto format(const MyType& t, format_context& ctx);
};
extern template struct formatter<MyType>;
...并且在.cpp
文件中定义:
auto formatter<MyType>::format(const MyType& t, format_context& ctx)
{
return format_to(ctx.out, "MyType: {}", ...);
}
主要优点是头文件变得更加轻便,所有自定义类型都可以进行前向声明,并且如果我想在某个翻译单元中具有单个类型的自定义格式,则不再需要包含整个世界。
然而,使用 {fmt} 实现自定义格式化的大多数示例将 `format()` 函数定义为针对 `format_context` 类型的模板函数。
template<typename FormatContext>
auto format(const MyType& t, FormatContext& ctx);
由于我需要预先声明所有可能类型的FormatContext
,因此它实际上无法与外部模板一起使用。这很容易出错。目前只能使用fmt::format_context
,如果不够用编译器会告诉我。
我想知道如果没有针对FormatContext
类型的格式函数模板化,会失去什么?在哪些情况下fmt::format_context
不足够?有没有更好的方法来定义这些自定义类型格式化程序,而不必将完整实现放在头文件中?我在考虑采用std::ostream
的方式,然后只需在需要使用{fmt}格式化我的类型时包含<fmt/ostream.h>
,但这在一定程度上违背了使用{fmt}的初衷。