带有外部模板的自定义类型 fmt 格式化程序,有啥缺点吗?

Posted

技术标签:

【中文标题】带有外部模板的自定义类型 fmt 格式化程序,有啥缺点吗?【英文标题】:Custom type fmt formatters with external termplates, any drawbacks?带有外部模板的自定义类型 fmt 格式化程序,有什么缺点吗? 【发布时间】:2020-07-24 14:29:12 【问题描述】:

我有一个标题,它为我的自定义类型定义了所有 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 类型声明format()。这很容易出错。目前,仅使用 fmt::format_context 有效,编译器会告诉我何时不再满足要求。

我想知道在FormatContext 类型上没有模板化格式函数会造成什么损失?在什么情况下fmt::format_context 不够用?有没有更好的方法来定义这些自定义类型格式化程序,而不必将完整的实现放在头文件中?我正在考虑采用 std::ostream 路线,然后只要我想用 fmt 格式化我的类型,就简单地包括 &lt;fmt/ostream.h&gt;,但这部分违背了首先使用 fmt 的目的。

【问题讨论】:

【参考方案1】:

由于没有在 FormatContext 类型上模板化格式函数,我失去了什么?

您将失去通过输出迭代器进行格式化的能力。 以前这意味着您将无法使用 format_to[_n]。但是在当前的master 中,这个限制有 已被删除,format_toformat_to_n 都可以使用 format_context。现在只有format string compilation 可能需要 自定义输出迭代器。

【讨论】:

以上是关于带有外部模板的自定义类型 fmt 格式化程序,有啥缺点吗?的主要内容,如果未能解决你的问题,请参考以下文章

带有编译时格式字符串检查的自定义 fmt 格式化函数

js时间类型的自定义转换库 datetime-fmt

理解 fmt formatter 解析函数

将任意文本添加到 fmt 的用户定义类型格式化程序

如何编写带有可变数量参数的F#printfn的自定义版本?

Apps 脚本:带有文本的自定义数字格式