If you like this content, you can contact me or follow me on Twitter 👍
The std::format is a text formatting library since C++20, which offers a safe and extensible alternative to the printf family of functions. It is intended to complement the existing C++ I/O streams library and reuse some of its infrastructure such as overloaded insertion operators for user-defined types.
#include <format>
compiler support | Text Formatting (C++20) | status |
---|---|---|
Visual Studio | VS 2019 16.10 / cl 19.29 | completed |
GCC | 13.1 | completed |
clang | 14 | completed |
Source: cppreference
#include <cstdio> // C library for Input/Output operations
const int answer { 42 };
printf( "The answer is %d ", answer );
const int answer { 42 };
std::cout << "The answer is " << answer << "\n";
const int answer { 42 };
std::cout << boost::format( "The answer is %") % answer;
const int answer { 42 };
ff::fmtll( std::cout, "The answer is {0}", answer );
const int answer { 42 };
std::cout << std::format( "The answer is {}", answer );
The {} indicates a replacement field like % in printf.
std::cout << std::format( "The answer is {}", 42 );
Writes the following output:
The answer is 42
std::cout << std::format( "I'd rather be {1} than {0}", "right", "happy" );
std::cout << std::format( "The answer is {{ }}", 42 );
Placeholder can contains a format specifiers. It starts with a colon: {[index]:[format specifiers]}
[[fill]align][sign][#][0][width][.precision][type]
minimum desired field width
std::cout << std::format( "{:5}", 42 );
std::cout << std::format( "{:{}}", 42, 5 );
Specifies optional characters and aligment
< left
> right
^ center
std::cout << std::format( "{:<20}", "left");
std::cout << std::format( "{:>20}", "right");
std::cout << std::format( "{:^20}", "centered");
std::cout << std::format( "{:-^20}", "centered");
- sign only for negative numbers (default)
+ sign for negative and positive numbers
scape display minus sign for negative numbers, a space for positive numbers
std::cout << std::format( "{:<5}", 42 );
std::cout << std::format( "{:<+5}", 42 );
std::cout << std::format( "{:< 5}", 42 );
std::cout << std::format( "{:< 5}", -42 );
enabled alternative formatting rules
integral types
- Hexadecimal format: inserts 0x or 0X at font
- Binray format: inserts 0b or 0B at font
- Octal format: inserts 0
floating-points types
- always show decimal separator, even without following digits
std::cout << std::format( "{:15d}", 42 );
std::cout << std::format( "{:15b}", 42 );
std::cout << std::format( "{:#15b}", 42 );
std::cout << std::format( "{:15X}", 42 );
std::cout << std::format( "{:#15X}", 42 );
only for floating-points types and strings types
const double pi { 3.1415 };
const int precision { 2 };
const int width { 15 };
std::cout << std::format( "{:15.2f}", pi );
std::cout << std::format( "{:15.{}f}", pi, precision );
std::cout << std::format( "{:{}.{}f}", pi, width, precision );
std::cout << std::format( "{0:{1}.{2}f}", pi, width, precision );
std::locale is supported in std::format
Note: Use
:L
to enable locale specific formatting for an argument.
#include <locale>
std::cout << std::format( locale( "en_US.UTF-8" ), "{:L}", 1024 );
std::cout << std::format( locale( "zh_CN.UTF-8" ), "{:L}", 1024 );
std::cout << std::format( locale( "de_DE.UTF-8" ), "{:L}", 1024 );
#include <chrono>
std::cout << std::format( "{:%d.%m.%Y}.", std::chrono::system_clock::now() ) << "\n";
void print_happy_birthday( const std::string_view& name, const std::chrono::year_month_day& birthday )
{
std::cout << std::format( "{0}'s birthday is {1:%Y-%m-%d}.", name, birthday ) << "\n";
}
using namespace std::chrono;
year_month_day birthday { 1976y / February / 1 };
std::string name { "Max Mustermann" };
print_happy_birthday( name , birthday );
#include <complex>
std::complex<double> c { 4.0, 8.0 };
std::cout << std::format( "{}", c);
Seperate parsing anf formatting in extension API
Need to provide a specialization of std::formater<> and imlpement
- formatter<>::parse()
- formatter<>::fomrat()
class Person
{
public:
Person() = delete;
Person( unsigned long long id, const std::string& firstName, const std::string& lastName ) noexcept
: _id( id ), _firstName( firstName ), _lastName( lastName ) {}
auto getId() const noexcept -> unsigned long long
{
return _id;
}
auto getFirstName() const noexcept -> const std::string&
{
return _firstName;
}
auto getLastName() const noexcept -> const std::string&
{
return _lastName;
}
private:
unsigned long long _id;
std::string _firstName;
std::string _lastName;
};
template<>
class std::formatter<Person>
{
public:
constexpr auto parse( auto& context )
{
}
auto format( const Person& person, auto& context )
{
}
};