fmt::format对自定义数据类型的支持

2024年7月9日

{fmt} 是一个先进的格式化库, 它提供了一种安全的printf系列函数的替代方案。 C语言中常见的格式化字符串不正确的问题能够在编译期就被检测出来。

这篇文章将要介绍如何让用户定义的数据类型也能支持ftm::format。 例如,我们有一个用户定义数据类型:

struct Data
{
    std::string name;
    int value;
};

我们希望能够像这样格式化输出字符串:

Data data{"amount", 100};
std::cout << fmt::format("Data: {}", data) << std::endl;

为了支持这个功能,我们需要添加formatter<Data>的偏特化实现:

template <>
struct fmt::formatter<Data> : fmt::formatter<std::string>
{
    template <typename FormatContext>
    auto format(const Data& data, FormatContext& ctx)
    {
        return formatter<std::string>::format(data.format(), ctx);
    }
};

这里是完整的实现代码:

#include <iostream>
#include <string>
#include <string_view>

#include <fmt/format.h>

struct Data
{
    std::string name;
    int value;

    std::string format() const
    {
        return fmt::format(R"({{name: "{}", value: {}}})", name, value);
    }
};

template <>
struct fmt::formatter<Data> : fmt::formatter<std::string>
{
    template <typename FormatContext>
    auto format(const Data& data, FormatContext& ctx)
    {
        return formatter<std::string>::format(data.format(), ctx);
    }
};

int main()
{
    Data data{"amount", 100};
    std::cout << fmt::format("Data: {}", data) << std::endl;
}

输出:

Data: {name: "amount", value: 100}