Formating Strings with std::format in C++20
C++20 introduced the long-awaited std::format function, a powerful tool for creating formatted strings, especially if we add some C++23 additions such as std::print and std::printl.
std::format(fmt, ARGS) produces or returns a string object holding the formatted result.
The fmt is a string with placeholders as {}.
This is a simple example:
cout << std::format("{} {}!", "Hello", "World");
The first argument into std::format is the format string is an object that represents the format string. The format string consists of
-
Ordinary characters (except { and }), which are copied unchanged to the output,
-
Escape sequences {{ and }}, which are replaced with { and } respectively in the output, and
-
Replacement fields, each having the following format:
- { arg-id (optional) }
- { arg-id (optional) : format-spec }
arg-id specifies the index of the argument in args whose value is to be used for formatting; if it is omitted, the arguments are used in order.
The arg-id's in a format string must all be present or all be omitted. Mixing manual and automatic indexing is an error.
format-spec is the format specification defined by the std::formatter specialization for the corresponding argument. Cannot start with }.
Prototypes (in Header <format>)
template< class... Args >
std::string format(std::format_string<Args...> fmt,
Args&&... args );
template< class... Args >
std::wstring format(std::wformat_string<Args...> fmt,
Args&&... args );
template< class... Args >
std::string format( const std::locale& loc,
std::format_string<Args...> fmt,
Args&&... args );
(3) (since C++20)
template< class... Args >
std::wstring format( const std::locale& loc,
std::wformat_string<Args...> fmt,
Args&&... args );
Using a non-const Expression with std::vformat
It is an error if the format string is not a constant expression unless it is initialized from the result of:
std::runtime_format(since C++26), orstd::vformat, which additionally requiresstd::make_format_args.
Look at these global functions:
std::string f1(std::string_view runtime_format_string)
{
// return std::format(runtime_format_string, "x", 42); // error
char v1[] = "x";
int v2 = 42;
return std::vformat(runtime_format_string, std::make_format_args(v1, v2)); // OK
}
std::string f2(std::string_view runtime_format_string)
{
return std::format(std::runtime_format(runtime_format_string), "x", 42); // OK (C++26)
}
Moreover, we can define a global function dynamic_print() that accepts a format string and any number of arguments, both generated dynamically:
template <typename... Args>
std::string dynamic_print(std::string_view rt_fmt_str, Args&&... args)
{
return std::vformat(rt_fmt_str, std::make_format_args(args...));
}