User-Defined Formatting in std::format -- Spencer Collyer
std::format allows us to format values quickly and safely. Spencer Collyer demonstrates how to provide formatting for a simple user-defined class.
User-Defined Formatting in std::format
by Spencer Collyer
From the article:
In a previous article [Collyer21], I gave an introduction to the
std::formatlibrary, which brings modern text formatting capabilities to C++.That article concentrated on the output functions in the library and how they could be used to write the fundamental types and the various string types that the standard provides.
Being a modern C++ library,
std::formatalso makes it relatively easy to output user-defined types, and this series of articles will show you how to write the code that does this.There are three articles in this series. This article describes the basics of setting up the formatting for a simple user-defined class. The second article will describe how this can be extended to classes that hold objects whose type is specified by the user of your class, such as containers. The third article will show you how to create format wrappers, special purpose classes that allow you to apply specific formatting to objects of existing classes.
A note on the code listings: The code listings in this article have lines labelled with comments like
// 1. Where these lines are referred to in the text of this article, it will be as ‘line1’ for instance, rather than ‘the line labelled // 1’.

Modern C++ offers elegant abstractions like std::ranges that promise cleaner, more expressive code without sacrificing speed. Yet, as with many abstractions, real-world performance can tell a more nuanced story—one that every engineer should verify through careful benchmarking.
In this post, we’ll take a closer look at how to extend the earlier callback wrapper mechanism to handle regular function pointers as well as member functions. Along the way, we’ll examine some of the subtleties of inferring function pointer types from callable objects—especially when lambdas with auto parameters enter the picture.
This post chronicles a month-long experiment using C++26 reflections to automate the generation of pybind11 bindings, blending the promise of modern metaprogramming with real-world complexity. It offers a candid look at what worked beautifully, what fell short, and what future language features could make reflection-driven automation even more powerful.