fmt::format Custom Data Structure

July 9, 2024

{fmt} is a modern formating library, it provides a safe replacement for the printf family of functions. Errors in format strings, which are a common source of vulnerabilities in C, are reported at compile time.

This article is about how to introduce ftm::format support for any user-defined structure. E.g., we have a user-defined data structure:

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

And we want to format its output string like this:

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

To support it, we need to implement partial specification of 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);
    }
};

The full source codes:

#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;
}

Output:

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