1

在我当前的项目中,我需要一个自定义的非常简单的“序列化”表示几个琐碎的数据传输对象 (DTO) 结构。在第一次想出一个定制的解决方案之后,那是一个大的 PITA,我有使用 {fmt} 的想法。

所以最近几天我正在通过fmt::formatter模板专业化机制的扩展来处理自定义类型的格式。因此,此博客您的文档非常有帮助。

经过一番折腾,我想出了一个非常通用的 poc 解决方案,它允许以多种自定义格式格式化结构,看起来有点像下面这样:

struct Inner {
    double x;
    std::string y;
    int z;
};
struct Outer {
    int a;
    std::string b;
    Inner inner;
};

template<>
struct reflection<Outer> {
    /*definition of class name and field names has to be provided manually...*/
};

template<>
struct reflection<Inner> {
    /*definition of class name and field names has to provided manually...*/
};

/*
...
couple dozend lines of meta programming and fmt::formatter specializations.
...
*/

auto outer = Outer{.a=1,.b="hello",.inner={.x=3.12,.y=" ",.z=2}};

std::string simple = fmt::format("{:s}", outer); // :s means format as simple
assert(simple == "a|hello|3.12| |2");
assert(fmt::format("{:s;}", outer) == "a;hello;3.12; ;2");

std::string  extended = fmt::format("{:e}",outer); // :e means format as extended
assert(extended == "Outer{.a=1, .b=hello, .inner=Inner{.x=3.12, .y= , .z=2}}");

显然,没有标准的方法来反映结构的字段和名称,因此必须手动提供反射结构,或者例如通过宏魔术。但这是一个不同的话题,我不想在这里讨论。- 如果我们幸运的话,我们会在 c++23 \o/ 中得到一些最小的编译时间反射。让我们希望!

我把所有这些放在了这个 repo中。

实际问题:

通过 {fmt} 提供的简单反射 API 格式化用户定义的类型是您认为未来可能对 {fmt} 进行扩展的东西吗?我想象一个场景,其中预定义了几个简单的格式化模式,用户只需要为他的类型提供反射。

有了这个,我什至可以看到像fmt::format("{:json,prety,tabwith=4}", outer)在地平线上的格式化表达式。

另外,也许我只是在重新发明轮子,所以如果有类似的东西,基于 {fmt} 那里 - 告诉我!:)

无论如何,感谢您为社区提供了很棒的工具,并祝贺您将其变成了 c++20!

问候,马丁

4

1 回答 1

1

通过 {fmt} 提供的简单反射 API 格式化用户定义的类型是您认为未来可能对 {fmt} 进行扩展的东西吗?

可能,但它必须是明确的选择加入,即此类类型不会以这种方式自动格式化,因为通常您需要更高级的表示而不是字段的集合。例如,您可能希望将点格式化为(x, y)而不是Point{.x=x, .y=y}.

于 2020-07-03T13:23:08.090 回答