我看过几篇关于 C++20 格式化库的自定义格式化程序的文章,但许多文章似乎有些微妙的错误或无法在我的工具链上编译。下面是一个我认为正确的示例,后面是 3 个具体问题。
#include <print>
struct CustomType {
int a;
};
template<>
struct std::formatter<CustomType> : std::formatter<int> {
// use format specifiers for int
using std::formatter<int>::parse;
auto format(CustomType const& x, auto & ctx) const {
auto out = ctx.out();
out = std::format_to(out, "[");
ctx.advance_to(out);
out = std::formatter<int>::format(x.a, ctx);
return std::format_to(out, "]");
}
};
int main() {
std::println("{:>2}", CustomType{1});
return 0;
}
这些说法正确吗?
format
方法应该在格式上下文类型上进行模板化,而不是使用 std::format_context
,正如许多在线示例所建议的那样。format
方法应该是const限定的。format_to()
时需要手动更新输出迭代器。大多数示例都忽略了这一点,并且似乎假设了 std::back_insert_iterator
,但据我所知,即使对于 std::format_context
,标准也没有强制要求。格式方法应该在格式上下文类型上模板化,而不是使用 std::format_context,正如许多在线示例所建议的那样。
是的。
格式化方法应该是const限定的。
是的。
使用format_to()时需要手动更新输出迭代器。大多数示例都忽略了这一点,并且似乎假设有一个 std::back_insert_iterator,但据我所知,即使对于 std::format_context,标准也没有强制要求。
是的。虽然该库倾向于对所有 char 类型使用相同的迭代器类型,但这并不是您可以做的唯一事情 - 并且如果
format
曾经使用具有迭代器类型(其位置很重要)的上下文进行实例化 -就像,char*
- 那么如果您不这样做 advance_to
,您的下一个格式将覆盖您的第一个格式。
因此,可能不太容易出现以下错误:
ctx.advance_to(std::format_to(ctx.out(), "["));
ctx.advance_to(std::formatter<int>::format(x.a, ctx));
return std::format_to(ctx.out(), "]");
尽管这无疑更乏味。如果对这类事情有更好的库支持那就太好了,但我不确定那会是什么样子。