{fmt} Formatting & Printing C++ Library

A fast and safe alternative to C stdio and C++ iostreams
  • faster than common implementations of iostreams, (s)printf, to_string and to_chars
  • convenient: format string syntax similar to Python's format
  • type-safe alternative to printf
  • can be used header-only or separately compiled

This article is based on {fmt} version 8.0.1

hello.cpp

// header-only mode not needed in compiler explorer:
// #define FMT_HEADER_ONLY

#include <fmt/core.h> 

int main () {
  fmt::print("Hello, World!\n");
}
Example Project Layout
demo/
  hello.cpp
  fmt/
    include/
      fmt/
        core.h
        …
    src/
$ g++ -I fmt/include -o greet hello.cpp
$ ./greet
Hello, World!

A minimum viable setup needs the files core.h, format.h and format-inl.h found in fmt/include/fmt/.

demo/hello.cpp

#include <fmt/core.h> 

int main () {
  fmt::print("Hello, World!\n");
}

demo/CMakeLists.txt

cmake_minimum_required(VERSION 3.10) 
project(FmtDemo) 
add_subdirectory(fmt)
add_executable(greet hello.cpp)                                                                                                                                                                                                                                                                                   
# set to C++17 (not required)
set_property(TARGET greet PROPERTY CXX_STANDARD 17)
target_link_libraries(greet fmt::fmt)
Project Layout
demo/
  CMakeLists.txt
  hello.cpp
  fmt/
    doc/
    include/
    src/
    support/
    test/
    CMakeLists.txt
    …
$ cd demo      # project directory
$ mkdir build  # directory for build output
$ cd build
$ cmake ..     # generate build scripts
$ make Scanning dependencies of target fmt
[ 20%] Building CXX object fmt/CMakeFiles/fmt.dir/src/format.cc.o
[ 40%] Building CXX object fmt/CMakeFiles/fmt.dir/src/os.cc.o
[ 60%] Linking CXX static library libfmt.a
[ 60%] Built target fmt
Scanning dependencies of target greet
[ 80%] Building CXX object CMakeFiles/greet.dir/hello.cpp.o
[100%] Linking CXX executable greet
[100%] Built target greet
$ ./greet
Hello, World!

Build {fmt} Library (Using CMake)

see here for more details

$ cd fmt
$ mkdir build   # directory for build output
$ cd build
$ cmake ..      # generate build scripts
$ make
... build process ...
$ sudo make install

demo/hello.cpp

#include <fmt/core.h> 
int main () {
  fmt::print("Hello, World!\n");
}

demo/CMakeLists.txt

cmake_minimum_required(VERSION 3.10) 
project(FmtDemo) 
find_package(fmt)
add_executable(greet hello.cpp)                                                                                                                                                                                                                                                                                   
# set to C++17 (not required)
set_property(TARGET greet PROPERTY CXX_STANDARD 17)
target_link_libraries(greet fmt::fmt)
$ cd demo      # project directory
$ mkdir build  # directory for build output
$ cd build
$ cmake ..     # generate build scripts
$ make
... build process ...
$ ./greet
Hello, World!
  • add the path to libfmt.a as library search path (gcc/clang: -L path)
  • link the library (gcc/clang: -l fmt)

hello.cpp

#include <fmt/core.h> 
int main () {
}
$ g++ -I path/to/fmt/include -o greet hello.cpp -L path/to/fmt/build -l fmt
$ ./greet
Hello, World!

1. Create {fmt} Project Using CMake

C:\users\jlp> cd fmt
C:\users\jlp> md build   # directory for build output
C:\users\jlp> cd build
C:\users\jlp> cmake ..   # generate build scripts

If Visual Studio was installed, CMake should have created a solution named FMT.sln and Project files (e.g. .vcxproj).

If you don't have Visual Studio installed on the build machine or want to target a specific Visual Studio Version, you need to specify the appropriate CMake generator and platform e.g., cmake -G "Visual Studio 16 2019" -A x64 ..

2. Add {fmt} Project To Your Solution

  • load an existing Visual Studio solution or create a new one
  • add the fmt project: File → Add → Existing Project… and select fmt.vcxproj
  • go to Project → Dependencies and add fmt as a dependency to all projects in the solution that should use fmt
  • go to Project → Properties select section Configuration Properties → C/C++ and add the path to folder fmt/include to the field Additional Include Directories
  • go to Project → Properties select section Configuration Properties → Linker
    • add the library file name fmtd.lib (debug build) or fmt.lib (release build) to the field Additional Dependencies
    • add the path to these library files, e.g. fmt/build/Debug or fmt/build/Release to the field Additional Library Directories
1. Create {fmt} Project Using CMake
$ cd fmt
$ mkdir build   # directory for build output
$ cd build
$ cmake ..      # generate build scripts

If Xcode is installed, CMake should have creaetd an .xcodeproj file.

If you don't have XCode installed on the build machine you need to specify the appropriate CMake generator cmake -G "Xcode"

2. Add fmt.xcodeproj To Your Workspace

Formatting

fmt::format(string)  std::string
fmt::format(fmt-stringformat-string, args...arguments...)  std::string
fmt::format_to(@output, fmt-stringformat-string, args...arguments...)
#include <fmt/core.h>
#include <iostream>

int main () {
auto str = fmt::format("in {}s\n", 47);
std::cout << str;  // in 47s
}

Printing

fmt::print(fmt-stringformat-string, arguments...)
fmt::print(file, format-string, args...arguments...)
#include <fmt/core.h>

int main () {
fmt::print("in {}s\n", 47);  // in 47s
fmt::print(stderr, "error: {}\n", 404);  // error: 404
}
<fmt/core.h> lightweight subset of formatting API
<fmt/format.h> full API = core.h + compile-time format checks, iterators, user-def. types, …
<fmt/args.h> core.h + dynamic format arguments
<fmt/chrono.h> format.h + date and time formatting
<fmt/compile.h> format.h + format string compilation
<fmt/color.h> format.h + terminal color and text style
<fmt/os.h> format.h + file output, system APIs
<fmt/ostream.h> format.h + std::ostream support
<fmt/printf.h> format.h + printf formatting
<fmt/ranges.h> format.h + formatting support for ranges and tuples
<fmt/xchar.h> format.h + wchar_t support
#include <fmt/core.h>

int main () {
int i = 7; 
double d = 3.4;
std::string s = "text";
fmt::print("fast {} output\n", s);
fmt::print("{} times\n", 47);
fmt::print("{} of {}\n", i, 9);
fmt::print("{}|{}|{}\n", di5);        
fmt::print("escaped {{ & }}\n");
}
fast text output
47 times
7 of 9
3.4|7|5
escaped { & }
#include <vector>
#include <array>
#include <fmt/ranges.h>

int main () {
std::vector<double> v {1.2, 5.6, 7.8};
std::array<int,4> a {2, 3, 4, 5};
fmt::print("v: {}\n", v);
fmt::print("a: {}\n", a);
fmt::print("{}\n", fmt::join(v,"|"));
}
v: [1.2, 5.6, 7.8]
a: [2, 3, 4, 5]
1.2|5.6|7.8
#include <fmt/core.h>

int main () {
fmt::print("{}, {}, {}\n", 'a', 'b', 'c');
fmt::print("{0}, {1}, {2}\n", 'a', 'b', 'c');
fmt::print("{2}, {1}, {0}\n", 'a', 'b', 'c');
fmt::print("{0}{1}{0}\n", "XX", "abc");
int i = 20; 
double d = 3.4;
fmt::print("{1} to {0}\n", i, 10);
fmt::print("{0} / {0}\n", d);
}

a, b, c a, b, c c, b, a XXabcXX 10 to 20 3.4 / 3.4
#include <fmt/format.h>  // literals

int main () {
int i = 2; 
double d = 4.567;
fmt::print("{x} + {x}\n", fmt::arg("x",d));
fmt::print("{pi} * {0}\n", i, fmt::arg("pi",3.14));
using namespace fmt::literals;
fmt::print("{y} | {x}\n", "x"_a=i, "y"_a=d);
}

4.567 + 4.567 3.14 * 2
4.567 | 2

{fmt} format specifications syntax overview

#include <fmt/core.h>

int main () {
int i = 18; 
fmt::print("{:+}\n", i);    // sign always
fmt::print("{:b}\n", i);    // binary
fmt::print("{:x}\n", i);    // hex
fmt::print("{:#x}\n", i);   // hex+prefix
}
#include <fmt/core.h>

int main () {

int i = 18;
fmt::print("{:6}\n", i);    // width 6
fmt::print("{:06}\n", i);   // 0-prefixed
fmt::print("\n");
fmt::print("{:>6}\n", i);   // align right
fmt::print("{:*>6}\n", i);  // align right
fmt::print("{:*^6}\n", i);  // center
fmt::print("{:*<6}\n", i);  // align left
}
    18
000018
    18
****18
**18**
18****
#include <fmt/core.h>

int main () {

double d = 34.567;
fmt::print("{:.3}\n", d);   // precision 3
fmt::print("{:+8.3}\n", d); // width 8
fmt::print("{:e}\n", d);    // exponential
fmt::print("{:.3e}\n", d);  // exp+prec
fmt::print("{:-<12}\n", ""); // line
fmt::print("{:*>+12.1e}\n", d);
}

34.6 +34.56 3.456700e+01 3.457e+01 ------------ ****+3.5e+01
#include <fmt/core.h>

int main () {
fmt::print("print to stdout\n");
fmt::print(stdout, "same");
fmt::print(stderr, "warning!");
}

This can be substantially faster than C's fprintf (see here) .

#include <fmt/os.h>

int main () {
fmt::ostream out = fmt::output_file("out.txt");
for (int ln = 0; ln < 4; ++ln) {
  out.print("line {}\n", ln);
}
}

out.txt

line·0\n
line·1\n
line·2\n
line·3\n
File Access Control Flags

Overwrite existing file, create file if it doesn't exist (default)

output_file("name")

output_file("name", fmt::file::WRONLY | fmt::file::CREATE)

Append to existing file, create file if it doesn't exist

output_file("name", fmt::file::WRONLY | fmt::file::CREATE | fmt::file::APPEND)

#include <cstdio>  // fopen
#include <fmt/core.h>

int main () {
std::FILE* file = std::fopen("out.txt","w");
for (int ln = 0; ln < 5; ++ln) {
  fmt::print(file, "line {}\n", ln);
}
std::fclose(file);
}

out.txt

line·0\n
line·1\n
line·2\n
line·3\n
line·4\n
Default: Compile-Time Checks

Requires a compiler with full support for consteval.

#include <fmt/core.h>

int main () {
double x = 3.456;
fmt::print("{0}\n", x);  
fmt::print("{1}\n", x);   only one arg
}
$ make

/home/demo/fmt/include/fmt/core.h:2432:40: error: …
2432 |  if (id >= num_args_) this->on_error("argument not found");
     |                       ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~

make[1]: *** [CMakeFiles/Makefile2:133: CMakeFiles/errors.dir/all] Error 2                   
make: *** [Makefile:84: all] Error 2
Opt-In: Runtime Checks (Throw Exceptions)
#include <fmt/core.h>

int main () {
double x = 3.456;
fmt::print("{0}\n", x);  
fmt::print(fmt::runtime("{1}\n"), x);  
}
$ make

$ ./run-demo
3.46                                                                    
terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  argument not found
Aborted
Default: Runtime Checks (Throw Exceptions)
#include <fmt/core.h>

int main () {
double x = 3.456;
fmt::print("{0}\n", x);  
fmt::print("{1}\n", x);  
}
$ make

$ ./run-demo
3.46                                                                    
terminate called after throwing an instance of 'fmt::v7::format_error'
  what():  argument not found
Aborted
Opt-In: Compile Time Checks
#include <fmt/format.h>

int main () {
double x = 3.456;
fmt::print(FMT_STRING("{0}\n"), x);  
fmt::print(FMT_STRING("{1}\n"), x);  
}
$ make

/home/demo/fmt/include/fmt/core.h:2432:40: error: …
2432 |  if (id >= num_args_) this->on_error("argument not found");
     |                       ~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~

make[1]: *** [CMakeFiles/Makefile2:133: CMakeFiles/errors.dir/all] Error 2                   
make: *** [Makefile:84: all] Error 2

{fmt} vs. C++20's std::format

  • names are defined in the fmt namespace instead of std
  • {fmt}'s width calculation doesn't yet (as of v8.0) use grapheme clusterization
  • {fmt} doesn't yet (as of v8.0) support all C++20 chrono types
#include <vector>
#include <fmt/format.h>

int main () {
fmt::print("some text\n");
fmt::print("A {} B\n", "and");
fmt::print("--------------------\n");

std::string w = "or"; fmt::print("A {} B\n", w); fmt::print("--------------------\n");
fmt::print("A{x}B{x}C\n", fmt::arg("x",w)); fmt::print("--------------------\n");
std::vector<char> v {'a','b','c','\0'}; fmt::print("{}\n", v.data()); }


some text
A and B

A or B
AorBorC
abc

{fmt} string type format specifications syntax overview

  • < align left (default)
  • ^ centered
  • > align right
#include <fmt/core.h>

int main () {
std::string s = "Ab C";
fmt::print("--------------------\n");

fmt::print("|{}|\n", s); fmt::print("--------------------\n");
fmt::print("|{:8}|\n", s); fmt::print("|{:<8}|\n", s); fmt::print("|{:^8}|\n", s); fmt::print("|{:>8}|\n", s); fmt::print("--------------------\n");
fmt::print("|{: >8}|\n", s); fmt::print("|{:*<8}|\n", s); fmt::print("|{:*^8}|\n", s); fmt::print("|{:*>8}|\n", s); }



|Ab C|
|Ab C | |Ab C | | Ab C | | Ab C|
| Ab C| |Ab C****| |**Ab C**| |****Ab C|
#include <fmt/format.h>

int main () {
std::string s = "ab";
int y = 4;
fmt::print("--------------------\n");

fmt::print("|{:{}}|\n", s, y); fmt::print("--------------------\n");
fmt::print("|{:{w}}|\n", s, fmt::arg("w",y)); fmt::print("--------------------\n");
fmt::print("|{:>{w}}|\n", s, fmt::arg("w",y)); fmt::print("--------------------\n");
using namespace fmt::literals; fmt::print("|{:>{w}}|\n", s, "w"_a = y); }
#include <fmt/format.h>

int main () {
std::string s = "abcde";
fmt::print("--------------------\n");

fmt::print("{:.0}\n", s); fmt::print("{:.1}\n", s); fmt::print("{:.2}\n", s); fmt::print("{:.3}\n", s); fmt::print("{:.4}\n", s); fmt::print("{:.5}\n", s); fmt::print("{:.6}\n", s); fmt::print("--------------------\n");
fmt::print("{:.{}}\n", s, 2); fmt::print("--------------------\n");
fmt::print("{:.{p}}\n", s, fmt::arg("p",3)); fmt::print("--------------------\n");
using namespace fmt::literals; fmt::print("{:.{p}}\n", s, "p"_a=4); }



a ab abc abcd abcde abcde
ab
abc
abcd
#include <fmt/core.h>

int main () {
fmt::print("{}\n", "abc");
fmt::print("{}\n", 12.34);
fmt::print("--------------------\n");

// only accept strings: fmt::print("{:s}\n", "abc"); fmt::print("{:s}\n", 12.34); }

abc 12.34
abc terminate called after throwing an instance of 'fmt::v7::format_error' what(): argument not found Aborted
#include <fmt/format.h>

int main () {
fmt::print("A {}\n", 'Z');
char c = 'B';
fmt::print("A {}\n", c);
fmt::print("A-{x}-{x}\n", fmt::arg("x",c));
}

{fmt} character type format specifications syntax overview

#include <fmt/core.h>

int main () {
char c = 'B';
fmt::print("--------------------\n");

fmt::print("|{:3}|\n", c); fmt::print("|{:<3}|\n", c); // left fmt::print("|{:^3}|\n", c); // centered fmt::print("|{:>3}|\n", c); // right fmt::print("--------------------\n");
fmt::print("|{: >3}|\n", c); fmt::print("|{:*<3}|\n", c); // left fmt::print("|{:*^3}|\n", c); // centered fmt::print("|{:*>3}|\n", c); // right }



|B | |B | | B | | B|
| B| |B**| |*B*| |**B|
#include <fmt/format.h>

int main () {
char c = 'B';
int y = 3;
fmt::print("--------------------\n");

fmt::print("|{:{}}|\n", c, y); fmt::print("--------------------\n");
fmt::print("|{:{w}}|\n", c, fmt::arg("w",y)); fmt::print("--------------------\n");
fmt::print("|{:>{w}}|\n", c, fmt::arg("w",y)); fmt::print("--------------------\n");
using namespace fmt::literals; fmt::print("|{:>{w}}|\n", c, "w"_a = y); }
#include <fmt/core.h>

int main () {
fmt::print("{}\n", 'B');
fmt::print("{}\n", 65);
fmt::print("--------------------\n");

// only accept strings: fmt::print("{:c}\n", 'B'); fmt::print("{:c}\n", 65); fmt::print("{:c}\n", "str"); }

B 65
B A terminate called after throwing an instance of 'fmt::v7::format_error' what(): argument not found Aborted
#include <fmt/format.h>

int main () {
int i = 18;
fmt::print("{:+06}\n", i);
fmt::print("{:*>#6x}\n", i);
}

{fmt} signed integer format specifications syntax overview

  • + always show sign
  • - show sign only for negative numbers (default)
  •   leading space for positive numbers, minus sign for negative numbers
#include <fmt/core.h>

int main () {
int x = -3;
int y = 47;
fmt::print("{} {}\n", x, y);
fmt::print("{:-} {:-}\n", x, y);
fmt::print("{:+} {:+}\n", x, y);
fmt::print("{: } {: }\n", x, y);
}
#include <fmt/core.h>

int main () {
int i = -47;
fmt::print("--------------------\n");

fmt::print("|{:5}|\n", i); fmt::print("|{:<5}|\n", i); // left fmt::print("|{:^5}|\n", i); // centered fmt::print("|{:>5}|\n", i); // right fmt::print("--------------------\n");
fmt::print("|{:*<5}|\n", i); // left fmt::print("|{:*^5}|\n", i); // centered fmt::print("|{:*>5}|\n", i); // right fmt::print("--------------------\n");
// sign-aware zero padding: fmt::print("|{:05}|\n", i); }



| -47| |-47 | | -47 | | -47|
|-47**| |*-47*| |**-47|
|-0047|
#include <fmt/format.h>

int main () {
int i = 47;
int w = 4;
fmt::print("--------------------\n");

fmt::print("|{:{}}|\n", i, w); fmt::print("--------------------\n");
fmt::print("|{:{w}}|\n", i, fmt::arg("w",w)); fmt::print("--------------------\n");
fmt::print("|{:<{w}}|\n", i, fmt::arg("w",w)); fmt::print("--------------------\n");
using namespace fmt::literals; fmt::print("|{:<{w}}|\n", i, "w"_a = w); }
#include <fmt/format.h>

int main () {
int i = 10000000;
fmt::print("{}\n", i);
auto s = fmt::format(
  std::locale("en_US.UTF-8"),"{:L}", i);
fmt::print("{}\n", s);
fmt::print("--------------------\n");
std::locale::global(std::locale("en_US.UTF-8"));
fmt::print("{}\n", i);
fmt::print("{:L}\n", i); 
}
#include <fmt/format.h>
int i = 10000000;
std::locale::global(std::locale("en_US.UTF-8"));
fmt::print("{}\n", i);
fmt::print("{:L}\n", i);
#include <fmt/core.h>

int main () {
int i = -47;
fmt::print("--------------------\n");
// decimal (default):
fmt::print("{}\n", i);
fmt::print("{:d}\n", i);
fmt::print("--------------------\n");
// binary (base 2):
fmt::print("{:b}\n", i);
fmt::print("{:#b}\n", i);
fmt::print("{:#B}\n", i);
fmt::print("--------------------\n");
// octal (base 8):
fmt::print("{:o}\n", i);
fmt::print("{:#o}\n", i);
fmt::print("--------------------\n");
// hexadecimal (base 16):
fmt::print("{:x}\n", i);
fmt::print("{:#x}\n", i);
fmt::print("{:#X}\n", i);
}



-47
-47

-101111
-0b101111
-0B101111

-57
-057

-2f
-0x2f
-0X2F
#include <fmt/format.h>

int main () {
unsigned u = 18;
fmt::print("{:06}\n", u);
fmt::print("{:*>#6x}\n", u);
}

{fmt} unsigned integer format specifications syntax overview

#include <fmt/core.h>

int main () {
unsigned u =  47;
fmt::print("--------------------\n");

fmt::print("|{:6}|\n", u); fmt::print("|{:<6}|\n", u); // left fmt::print("|{:^6}|\n", u); // centered fmt::print("|{:>6}|\n", u); // right fmt::print("--------------------\n");
fmt::print("|{:*<6}|\n", u); // left fmt::print("|{:*^6}|\n", u); // centered fmt::print("|{:*>6}|\n", u); // right fmt::print("--------------------\n");
// sign-aware zero padding: fmt::print("|{:06}|\n", u); }



| 47| |47 | | 47 | | 47|
|47****| |**47**| |****47|
|000047|
#include <fmt/format.h>

int main () {
unsigned u = 47;
int w = 4;
fmt::print("--------------------\n");

fmt::print("|{:{}}|\n", u, w); fmt::print("--------------------\n");
fmt::print("|{:{w}}|\n", u, fmt::arg("w",w)); fmt::print("--------------------\n");
fmt::print("|{:<{w}}|\n", u, fmt::arg("w",w)); fmt::print("--------------------\n");
using namespace fmt::literals; fmt::print("|{:<{w}}|\n", u, "w"_a = w); }
#include <fmt/format.h>

int main () {
unsigned u = 10000000;
fmt::print("{}\n", u);
auto s = fmt::format(
  std::locale("en_US.UTF-8"),"{:L}", u);
fmt::print("{}\n", s);
fmt::print("--------------------\n");
std::locale::global(std::locale("en_US.UTF-8"));
fmt::print("{}\n", u);
fmt::print("{:L}\n", u); 
}
#include <fmt/format.h>
unsigned u = 10000000;
std::locale::global(std::locale("en_US.UTF-8"));
fmt::print("{}\n", u);
fmt::print("{:L}\n", u);
#include <fmt/core.h>

int main () {
unsigned u = 47;
fmt::print("--------------------\n");
// decimal (default):
fmt::print("{}\n", u);
fmt::print("{:d}\n", u);
fmt::print("--------------------\n");
// binary (base 2):
fmt::print("{:b}\n", u);
fmt::print("{:#b}\n", u);
fmt::print("{:#B}\n", u);
fmt::print("--------------------\n");
// octal (base 8):
fmt::print("{:o}\n", u);
fmt::print("{:#o}\n", u);
fmt::print("--------------------\n");
// hexadecimal (base 16):
fmt::print("{:x}\n", u);
fmt::print("{:#x}\n", u);
fmt::print("{:#X}\n", u);
}



47
47

101111
0b101111
0B101111

57
057

2f
0x2f
0X2F
#include <fmt/format.h>

int main () {
double d = 3.591;
fmt::print("{:08.4}\n", d);
fmt::print("{:*>+10.1e}\n", d);
}

{fmt} floating point number format specifications syntax overview

  • + always show sign
  • - show sign only for negative numbers (default)
  •   leading space for positive numbers, minus sign for negative numbers
#include <fmt/core.h>

int main () {
double x = -3.1;
double y = 4.7;
fmt::print("{} {}\n", x, y);
fmt::print("{:-} {:-}\n", x, y);
fmt::print("{:+} {:+}\n", x, y);
fmt::print("{: } {: }\n", x, y);

float inf = std::numeric_limits<float>::infinity(); float nan = std::numeric_limits<float>::quiet_NaN(); fmt::print("{} {}\n", inf, nan); fmt::print("{:+} {:+}\n", inf, nan); fmt::print("{: } {: }\n", inf, nan); }



-3.1 4.7
-3.1 4.7
-3.1 +4.7
-3.1  4.7

inf nan +inf +nan inf nan
#include <fmt/core.h>

int main () {
double x = 12.345;
fmt::print("--------------------\n");

fmt::print("|{:8}|\n", x); fmt::print("|{:<8}|\n", x); fmt::print("|{:^8}|\n", x); fmt::print("|{:>8}|\n", x); fmt::print("--------------------\n");
fmt::print("|{:*<8}|\n", x); fmt::print("|{:*^8}|\n", x); fmt::print("|{:*>8}|\n", x); fmt::print("--------------------\n");
// sign-aware zero padding: fmt::print("|{:08}|\n", -5.6); }



| 12.345| |12.345 | | 12.345 | | 12.345|
|12.345**| |*12.345*| |**12.345|
|-00005.6|
#include <fmt/format.h>

int main () {
double x = 1.2;
int w = 5;
fmt::print("--------------------\n");

fmt::print("|{:{}}|\n", x, w); fmt::print("--------------------\n");
fmt::print("|{:{w}}|\n", x, fmt::arg("w",w)); fmt::print("--------------------\n");
fmt::print("|{:>{w}}|\n", x, fmt::arg("w",w)); fmt::print("--------------------\n");
using namespace fmt::literals; fmt::print("|{:>{w}}|\n", x, "w"_a = w); }




|1.2 |
|1.2 |
| 1.2|
| 1.2|
#include <fmt/format.h>

int main () {
double x = 12.345;
fmt::print("--------------------\n");
// with default format

fmt::print("{:.0}\n", x); fmt::print("{:.1}\n", x); fmt::print("{:.2}\n", x); fmt::print("{:.3}\n", x); fmt::print("{:.4}\n", x); fmt::print("{:.5}\n", x); fmt::print("{:.6}\n", x); fmt::print("{:.3}\n", 0.5); fmt::print("{:.1}\n", 0.123); fmt::print("--------------------\n"); // with exponential format fmt::print("{:.0e}\n", x); fmt::print("{:.1e}\n", x); fmt::print("{:.2e}\n", x); fmt::print("{:.3e}\n", x); fmt::print("{:.4e}\n", x); fmt::print("{:.5e}\n", x); fmt::print("{:.6e}\n", x); fmt::print("--------------------\n"); // width + precision
fmt::print("{:6.3}\n", x); // width 6, prec 3 fmt::print("{:06.3}\n", x); // 0-prefixed fmt::print("--------------------\n"); // with fixed format fmt::print("{:.0f}\n", x); fmt::print("{:.1f}\n", x); fmt::print("{:.2f}\n", x); fmt::print("{:.3f}\n", x); fmt::print("{:.4f}\n", x); fmt::print("{:.5f}\n", x); fmt::print("{:.6f}\n", x); fmt::print("{:.3f}\n", 0.5); fmt::print("{:.1f}\n", 0.123); fmt::print("--------------------\n"); // precision determined by argument: fmt::print("{:.{}}\n", x, 2); fmt::print("--------------------\n"); fmt::print("{:.{p}}\n", x, fmt::arg("p",3)); fmt::print("--------------------\n"); using namespace fmt::literals; fmt::print("{:.{p}}\n", x, "p"_a=4); }



10 1e+01 12 12.3 12.35 12.345 12.345 0.5 0.1
12.3 0012.3
// precision determined by argument
fmt::print("{:.{}}\n", x, 2);
fmt::print("--------------------\n");

fmt::print("{:.{p}}\n", x, fmt::arg("p",3)); fmt::print("--------------------\n");
using namespace fmt::literals; fmt::print("{:.{p}}\n", x, "p"_a=4);
// with exponential format
fmt::print("{:.0e}\n", x);
fmt::print("{:.1e}\n", x);
fmt::print("{:.2e}\n", x);
fmt::print("{:.3e}\n", x);
fmt::print("{:.4e}\n", x);
fmt::print("{:.5e}\n", x);
fmt::print("{:.6e}\n", x);

1e+01
1.2e+01
1.23e+01
1.235e+01
1.2345e+01
1.23450e+01
1.234500e+01
// with fixed format
fmt::print("{:.0f}\n", x);
fmt::print("{:.1f}\n", x);
fmt::print("{:.2f}\n", x);
fmt::print("{:.3f}\n", x);
fmt::print("{:.4f}\n", x);
fmt::print("{:.5f}\n", x);
fmt::print("{:.6f}\n", x);
fmt::print("{:.3f}\n", 0.5);
fmt::print("{:.1f}\n", 0.123);

12
12.3
12.35
12.345
12.3450
12.34500
12.345000
0.500
0.1
#include <fmt/format.h>

int main () {
double x = 123.45;
fmt::print("{}\n", x);
auto s = fmt::format(
  std::locale("de_DE.UTF-8"),"{:L}", x);
fmt::print("{}\n", s);
fmt::print("--------------------\n");
std::locale::global(std::locale("de_DE.UTF-8"));
fmt::print("{}\n", x);
fmt::print("{:L}\n", x); 
}
#include <fmt/format.h>
double x = 123.45;
std::locale::global(std::locale("de_DE.UTF-8"));
fmt::print("{}\n", x);
fmt::print("{:L}\n", x);
#include <fmt/core.h>

int main () {
double x = 12.345;
fmt::print("--------------------\n");
// general (default):
fmt::print("{}\n", x);
fmt::print("{:g}\n", x);
fmt::print("{:g}\n", 100000000.);
fmt::print("{:G}\n", 100000000.);
fmt::print("--------------------\n");
// scientific notation:
fmt::print("{:e}\n", x);
fmt::print("{:E}\n", x);
fmt::print("--------------------\n");
// fixed point notation:
fmt::print("{:f}\n", x);
fmt::print("{:f}\n", 1./0);
fmt::print("{:F}\n", 1./0);
fmt::print("--------------------\n");
// force decimal point / trailing 0s:
fmt::print("{:}\n", 1.0);
fmt::print("{:#}\n", 1.0);
fmt::print("--------------------\n");
// hexadecimal (base 16):
fmt::print("{:a}\n", x);
fmt::print("{:A}\n", x);
}



12.345                
12.345                
1e+08
1E+08

1.234500e+01          
1.234500E+01          

12.345000
inf
INF

1
1.0

0x1.8b0a3d70a3d71p+3  
0X1.8B0A3D70A3D71P+3
#include <string_view>
#include <limits>
#include <fmt/core.h>

template <typename T>
void print_table (std::string_view label) {
    using lim = std::numeric_limits<T>;
    fmt::print("{0:-^40}\n{1}\n{0:-^40}\n","",label);
    fmt::print("lowest        {: .20}\n", lim::lowest());
    fmt::print("min           {: .20}\n", lim::min());
    fmt::print("max           {: .20}\n", lim::max());
    fmt::print("denorm_min    {: .20}\n", lim::denorm_min());
    fmt::print("epsilon       {: .20}\n", lim::epsilon());
    fmt::print("round_error   {: .20}\n", lim::round_error());
    fmt::print("min_exponent  {: }\n", lim::min_exponent);
    fmt::print("max_exponent  {: }\n", lim::max_exponent);
    fmt::print("quiet_NaN      {}\n", lim::quiet_NaN());
    fmt::print("digits        {: }\n", lim::digits);
    fmt::print("digits10      {: }\n", lim::digits10);
    fmt::print("+0            {: }\n", T(0));
    fmt::print("-0            {: }\n", T(-0.0));
} 

int main () {
    print_table<float>("FLOAT");
    print_table<double>("DOUBLE");
    print_table<long double>("LONG DOUBLE");
}
----------------------------------------
FLOAT
----------------------------------------
lowest        -3.4028234663852885981e+38
min            1.175494350822287508e-38
max            3.4028234663852885981e+38
denorm_min     1.4012984643248170709e-45
epsilon        1.1920928955078125e-07
round_error    0.5
min_exponent  -125
max_exponent   128
quiet_NaN      nan
digits         24
digits10       6
+0             0
-0            -0
#include <fmt/core.h>

int main () {
bool t = true;
fmt::print("{}\n", t);
fmt::print("{:d}\n", t);
fmt::print("{}\n", false);
}

{fmt} bool format specifications syntax overview

#include <fmt/core.h>

int main () {
bool b = true;
fmt::print("--------------------\n");

fmt::print("|{:6}|\n", b); fmt::print("|{:<6}|\n", b); // left fmt::print("|{:^6}|\n", b); // centered fmt::print("|{:>6}|\n", b); // right fmt::print("--------------------\n");
fmt::print("|{: >6}|\n", b); fmt::print("|{:*<6}|\n", b); // left fmt::print("|{:*^6}|\n", b); // centered fmt::print("|{:*>6}|\n", b); // right }



|true | |true | | true | | true|
| true| |true**| |*true*| |**true|
#include <fmt/format.h>

int main () {
bool b = true;
int y = 6;
fmt::print("--------------------\n");

fmt::print("|{:{}}|\n", b, y); fmt::print("--------------------\n");
fmt::print("|{:{w}}|\n", b, fmt::arg("w",y)); fmt::print("--------------------\n");
fmt::print("|{:>{w}}|\n", b, fmt::arg("w",y)); fmt::print("--------------------\n");
using namespace fmt::literals; fmt::print("|{:>{w}}|\n", b, "w"_a = y); }




|true |
|true |
| true|
| true|
#include <fmt/core.h>

int main () {
bool b = true;
fmt::print("--------------------\n");

fmt::print("{}\n", b); fmt::print("{:s}\n", b); fmt::print("{:d}\n", b); fmt::print("--------------------\n");
fmt::print("{:b}\n", b); fmt::print("{:#b}\n", b); fmt::print("{:#B}\n", b); fmt::print("--------------------\n");
fmt::print("{:o}\n", b); fmt::print("{:#o}\n", b); fmt::print("--------------------\n");
fmt::print("{:x}\n", b); fmt::print("{:#x}\n", b); fmt::print("{:#X}\n", b); }



true true 1
1 0b1 0B1
1 01
1 0x1 0X1
#include <fmt/format.h>

int main () {
int i = 12;
int* pi = &i;
fmt::print("{}\n", fmt::ptr(&i));
fmt::print("{}\n", fmt::ptr(pi));
}



0x7ffe55a4e7ac
0x7ffe55a4e7ac

{fmt} pointer value format specifications syntax overview

#include <fmt/format.h>

int main () {
int i = 12;
int* pi = &i;
auto const p = fmt::ptr(pi);
fmt::print("--------------------\n");

fmt::print("|{:18}|\n", p); fmt::print("|{:<18}|\n", p); fmt::print("|{:^18}|\n", p); fmt::print("|{:>18}|\n", p); fmt::print("--------------------\n");
fmt::print("|{: >18}|\n", p); fmt::print("|{:*<18}|\n", p); fmt::print("|{:*^18}|\n", p); fmt::print("|{:*>18}|\n", p); }





| 0x7ffe55a4e7ac| |0x7ffe55a4e7ac | | 0x7ffe55a4e7ac | | 0x7ffe55a4e7ac|
| 0x7ffe55a4e7ac| |0x7ffe55a4e7ac****| |**0x7ffe55a4e7ac**| |****0x7ffe55a4e7ac|
#include <fmt/format.h>

int main () {
int i = 12;
int* pi = &i;
auto const p = fmt::ptr(pi);
int const w = 18;
fmt::print("--------------------\n");

fmt::print("|{:{}}|\n", p, w); fmt::print("--------------------\n");
fmt::print("|{:{w}}|\n", p, fmt::arg("w",w)); fmt::print("--------------------\n");
fmt::print("|{:<{w}}|\n", p, fmt::arg("w",w)); fmt::print("--------------------\n");
using namespace fmt::literals; fmt::print("|{:<{w}}|\n", p, "w"_a = w); }






| 0x7ffe55a4e7ac|
| 0x7ffe55a4e7ac|
|0x7ffe55a4e7ac |
|0x7ffe55a4e7ac |
#include <fmt/format.h>

int main () {
int i = 12;
fmt::print("--------------------\n");

fmt::print("{}\n", fmt::ptr(&i)); fmt::print("--------------------\n");
fmt::print("{:p}\n", fmt::ptr(&i)); fmt::print("--------------------\n");
// fmt::print("{:p}\n", 123); // ERROR }



0x7ffe55a4e7ac
0x7ffe55a4e7ac
terminate called after throwing an instance of 'fmt::v7::format_error' what(): argument not found Aborted
#include <utility>  // pair
#include <fmt/ranges.h>

int main () {
std::pair<char,int> t {'a', 2};
fmt::print("{}\n", t);
}
#include <tuple>
#include <fmt/ranges.h>

int main () {
std::tuple<char,int,double> t {'a', 2, 3.4};
fmt::print("{}\n", t);
fmt::print("{}\n", fmt::join(t,"|"));
fmt::print("{}\n", fmt::join(t,""));
}



('a', 2, 3.4)
a|2|3.4
a23.4
#include <vector>
#include <fmt/ranges.h>
#include <array>
#include <set>
#include <map>

int main () {
std::vector<int> v {2,3,4,5};
fmt::print("{}\n", v);
fmt::print("{}\n", fmt::join(v,"|"));
fmt::print("{:03}\n", fmt::join(v,"|"));
fmt::print("--------------------\n");
std::array<int,4> a {2,3,4,5};
fmt::print("{}\n", a);
fmt::print("{}\n", fmt::join(a," | ")); 
fmt::print("--------------------\n");
std::set<int> s {2,3,4,5};
fmt::print("{}\n", s);
fmt::print("{}\n", fmt::join(s,""));
fmt::print("--------------------\n");
std::map<char,int> m {{'a',2},{'b',4}};
fmt::print("{}\n", m);
fmt::print("{}\n", fmt::join(m,""));
}



[2, 3, 4, 5]
2|3|4|5
002|003|004|005
#include <array>
#include <fmt/ranges.h>

int main () {
std::array<int,4> a {2,3,4,5};
fmt::print("{}\n", a);
fmt::print("{}\n", fmt::join(a," | "));
}



[2, 3, 4, 5]
2 | 3 | 4 | 5
#include <set>
#include <fmt/ranges.h>

int main () {
std::set<int> s {2,3,4,5};
fmt::print("{}\n", s);
fmt::print("{}\n", fmt::join(s,""));
}
#include <map>
#include <fmt/ranges.h>

int main () {
std::map<char,int> m {{'a',2},{'b',4}};
fmt::print("{}\n", m);
fmt::print("{}\n", fmt::join(m,""));
}



[('a', 2),('b', 4)]
('a', 2)('b', 4)
#include <fmt/chrono.h>

int main () {
auto now = std::chrono::system_clock::now();
fmt::print("{}\n", now);
fmt::print("{:%S}\n", now);
fmt::print("{:%d/%m}\n", now);

using tp = std::chrono::time_point<
std::chrono::system_clock, std::chrono::seconds>;
fmt::print("--------------\n");
fmt::print("{:%S}\n", tp(std::chrono::seconds(47)));
using namespace std::chrono_literals;
fmt::print("{}\n", tp(32s));
fmt::print("{:%S}\n", tp(32s));
}


2021-07-04 18:03:09 09 07/04
#include <fmt/chrono.h>

int main () {
std::time_t tp = std::time(nullptr);             
auto const t = fmt::localtime(tp);
fmt::print("{}\n", t);    // no output
fmt::print("{:%D}\n", t); // %m/%d/%y
fmt::print("{:%F}\n", t); // ISO 8601
}
#include <fmt/chrono.h>

int main () {
auto const t = std::chrono::system_clock::now();
fmt::print("{}\n", t);
fmt::print("{:%Y-%m-%d}\n", t); 
fmt::print("-----------------------------------------------\n");
fmt::print("std. date + time          %c   {:%c}\n", t);
fmt::print("alt. date + time          %Ec  {:%Ec}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("ISO 8601 date             %F   {:%F}\n", t);
fmt::print("%m/%d/%y                  %D   {:%D}\n", t);
fmt::print("localized date            %x   {:%x}\n", t);
fmt::print("alt. date                 %Ex  {:%Ex}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("%H:%M:%S                  %T   {:%T}\n", t);
fmt::print("%H:%M                     %R   {:%R}\n", t);
fmt::print("localized 12-hour clock   %r   {:%r}\n", t);
fmt::print("localized time            %X   {:%X}\n", t);
fmt::print("alt. time                 %EX  {:%EX}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("year (last 2 digits)      %y   {:%y}\n", t);
fmt::print("year (4 digits)           %Y   {:%Y}\n", t);
fmt::print("century                   %C   {:%C}\n", t);
fmt::print("alt. localized repr.      %Ey  {:%Ey}\n", t);
fmt::print("alt. localized repr.      %EY  {:%EY}\n", t);
fmt::print("ISO 8601 week-based year  %G   {:%G}\n", t);
fmt::print("ISO 8601 week-based year  %g   {:%g}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("month                     %m   {:%m}\n", t);
fmt::print("locale-dep.               %Om  {:%Om}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("abbrev. name of month     %a   {:%a}\n", t);
fmt::print("full name of month        %A   {:%A}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("week (1st:Mon)  00-53     %W   {:%W}\n", t);
fmt::print("week (1st:Sun)  00-53     %U   {:%U}\n", t);
fmt::print("week (ISO 8601) 01-53     %V   {:%V}\n", t);
fmt::print("localized numerals        %OW  {:%OW}\n", t);
fmt::print("localized numerals        %OU  {:%OU}\n", t);
fmt::print("localized numerals        %OV  {:%OV}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("2-digit day of month      %d   {:%d}\n", t);
fmt::print("1-digit day of month      %e   {:%e}\n", t);   
fmt::print("localized numerals        %Od  {:%Od}\n", t);
fmt::print("localized numerals        %Oe  {:%Oe}\n", t);   
fmt::print("-----------------------------------------------\n");
fmt::print("weekday (Mon:1 - Sun:7)   %u   {:%u}\n", t);
fmt::print("weekday (Sun:0 - Sat:6)   %w   {:%w}\n", t);
fmt::print("local.  (Mon:1 - Sun:7)   %Ou  {:%Ou}\n", t);
fmt::print("local.  (Sun:0 - Sat:6)   %Ow  {:%Ow}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("abbrev. name of day       %b   {:%b}\n", t);
fmt::print("full name of day          %B   {:%B}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("day of year               %j   {:%j}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("hours (24-based)          %H   {:%H}\n", t);
fmt::print("hours (12-based)          %I   {:%I}\n", t);
fmt::print("localized numerals        %OH  {:%OH}\n", t);
fmt::print("localized numerals        %OI  {:%OI}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("minutes                   %M   {:%M}\n", t);
fmt::print("localized numerals        %OM  {:%OM}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("seconds                   %S   {:%S}\n", t);
fmt::print("localized numerals        %OS  {:%OS}\n", t);
fmt::print("-----------------------------------------------\n");
fmt::print("offset from UTC           %z   {:%z}\n", t);
fmt::print("time zone abbrev.         %Z   {:%Z}\n", t);
}
fmt::print("{}\n", t);
fmt::print("{:%Y-%m-%d}\n", t); 
fmt::print("--------------------\n");

fmt::print("{:%F}\n", t); // ISO 8601 fmt::print("{:%D}\n", t); // %m/%d/%y fmt::print("--------------------\n");
fmt::print("{:%c}\n", t); // localized
2021-07-04 18:03:09
2021-07-04

2021-07-04 07/04/21
Sun Jul 4 18:03:09 2021
fmt::print("{:%y}\n", t); // year
fmt::print("{:%Y}\n", t); // year
fmt::print("{:%m}\n", t); // month
fmt::print("{:%b}\n", t); 
fmt::print("{:%B}\n", t);
fmt::print("{:%d}\n", t); // day of month
fmt::print("{:%a}\n", t); 
fmt::print("{:%A}\n", t);
fmt::print("{:%u}\n", t); // weekday
fmt::print("{:%w}\n", t); // weekday (US)
fmt::print("{:%j}\n", t); // day of year
fmt::print("{:%H}\n", t); // /24 hours
fmt::print("{:%M}\n", t); // minutes
fmt::print("{:%S}\n", t); // seconds
fmt::print("{:%T}\n", t); // %H:%M:%S
fmt::print("{:%I}\n", t); // /12 hours
fmt::print("{:%p}\n", t); // AM/PM

separate compilation example

i.e., types T for which an operator << (std::ostream&, T const&) is defined

#include <iostream>
#include <string>

#include <fmt/ostream.h>

struct point2d {
  int x;
  int y;

  point2d(int x_, int y_): x(x_), y(y_) {}

  friend std::ostream&   operator << (std::ostream& os, point2d const& p)   {
    return os << '(' << p.x << ',' << p.y << ')';
  }
};

int main () {
std::string s = fmt::format("Position is {}", point2d{7,9});
// s = "Position is (7,9)"

std::cout << s << '\n';

fmt::print("{}\n", s);
}

Any type T can be made formattable/printable by specializing template fmt::formatter<T>.

If a type provides both a formatter specialization and an implicit conversion to an already formattable type, the specialization takes precedence over the conversion.

C++20's std::format works similarly, it uses specializations of std::formatter.

#include <fmt/format.h>

struct Point { double x, y; };

template <>
class fmt::formatter<Point> {
  // format specification storage
  char presentation_ = 'f';
public:
  // parse format specification and store it:
  constexpr auto   parse (format_parse_context& ctx) {     auto i = ctx.begin(), end = ctx.end();
    if (i != end && (*i == 'f' || *i == 'e')) {
      presentation_ = *i++;
    }
    if (i != end && *i != '}') {
      throw format_error(        "invalid format");
    }
    return i;  }

  // format a value using stored specification:
  template <typename FmtContext>
  constexpr auto   format (Point const& p,           FmtContext& ctx) const {     // note: we can't use ternary operator '?:' in a constexpr
    switch (presentation_) {
    default:
    // 'ctx.out()' is an output iterator
    case 'f': return format_to(ctx.out(),               "({:f}, {:f})", p.x, p.y);
    case 'e': return format_to(ctx.out(),               "({:e}, {:e})", p.x, p.y);
    }  }
};

int main () {
  Point p {1.2, 3.4};
  fmt::print("{}\n", p);
  fmt::print("{:f}\n", p);
  fmt::print("{:e}\n", p);
}
(1.2, 3.4)
(1.2, 3.4)
(1.2e+00, 3.4e+00)
#include <fmt/format.h>

enum class color {red, green, blue};

template <>
struct fmt::formatter<color> :   formatter<string_view>
{
  // use inherited 'formatter<string_view>::parse'…

  // … and only implement 'format':
  template <typename FmtContext>
  auto format (color c, FmtContext& ctx) {
    string_view name = "unknown";
    switch (c) {
      case color::red:         name = "red"; break;
      case color::green:       name = "green"; break;
      case color::blue:        name = "blue"; break;
    }
    return formatter<string_view>::format(name, ctx);
  }
};

int main () {
  fmt::print("|{:>10}|\n", color::blue);
}
A custom container / range type T needs
  • either member functions T::begin() and T::end()
  • or free standing functions begin(T const&) and end(T const&)

that return iterators or pointers whose value type is supported by {fmt} or for which a custom {fmt}-formatter is defined.

Example 1: Wrapper around a standard container

value type of iterator is int which is printable by {fmt}

#include <vector>
#include <fmt/ranges.h>

class IntList {
  std::vector<int> v_;
public:
  explicit 
  IntList (std::initializer_list<int> il): v_{il} {}
  [[nodiscard]] auto begin () const noexcept { return v_.begin(); }
  [[nodiscard]] auto end ()   const noexcept { return v_.end(); }
};

int main () {
  IntList l {4,8,15,16,23,42};
  fmt::print("numbers: {}\n", l);
}
numbers: [4, 8, 15, 16, 23, 24]

Example 2: Type for which begin/end return pointers

value type of iterators is double which is printable by {fmt}

#include <fmt/ranges.h>

class Point4 {
  double v_ [4];
public:
  explicit 
  Point4 (double x, double y, double z, double w): v_{x,y,z,w} {}
  [[nodiscard]] double x () const noexcept { return v_[0]; }
  [[nodiscard]] double y () const noexcept { return v_[1]; }
  [[nodiscard]] double z () const noexcept { return v_[2]; }
  [[nodiscard]] double w () const noexcept { return v_[3]; }
  [[nodiscard]] double const* begin () const noexcept { return v_; }
  [[nodiscard]] double const* end ()   const noexcept { return v_+4; }
};

int main () {
  Point4 v {4.7,2.,1.,3.2};
  fmt::print("point: {}\n", v);
}
#include <fmt/color.h>

int main () {
std::string s = "Abc\n";
fmt::print(fmt::emphasis::bold, s);                                              
fmt::print(fmt::emphasis::italic, s);                                            
fmt::print(fmt::emphasis::bold | fmt::emphasis::italic, s);
fmt::print(fg(fmt::color::red), s);                                              
fmt::print(fg(fmt::color::green), s);                                            
fmt::print(fg(fmt::color::blue), s);
fmt::print(bg(fmt::color::red), s);                                              
fmt::print(bg(fmt::color::green), s);                                            
fmt::print(bg(fmt::color::blue), s);
fmt::print(fmt::emphasis::bold | bg(fmt::color::red), s);
fmt::print(fmt::emphasis::bold | fmt::emphasis::italic | bg(fmt::color::red), s); 
}
fmt::print(fmt::emphasis::bold, s);                                              
fmt::print(fmt::emphasis::italic, s);                                            
fmt::print(fmt::emphasis::bold | fmt::emphasis::italic, s);
fmt::print(fg(fmt::color::red), s);                                              
fmt::print(fg(fmt::color::green), s);                                            
fmt::print(fg(fmt::color::blue), s);
fmt::print(bg(fmt::color::red), s);                                              
fmt::print(bg(fmt::color::green), s);                                            
fmt::print(bg(fmt::color::blue), s);
fmt::print(fmt::emphasis::bold | bg(fmt::color::red), s);
fmt::print(fmt::emphasis::bold | fmt::emphasis::italic | bg(fmt::color::red), s);

Only available for numeric types: int, float, double, bool, char, …

#include <fmt/format.h>

int main () {
int i = 10000000;
fmt::print("{}\n", i);
auto s = fmt::format(
  std::locale("en_US.UTF-8"),"{:L}", i);
fmt::print("{}\n", s);
fmt::print("--------------------\n");
std::locale::global(std::locale("en_US.UTF-8"));
fmt::print("{}\n", i);
fmt::print("{:L}\n", i); 
}
#include <fmt/format.h>
int i = 10000000;
std::locale::global(std::locale("en_US.UTF-8"));
fmt::print("{}\n", i);
fmt::print("{:L}\n", i);
#include <fmt/format.h>

int main () {
double x = 123.45;
fmt::print("{}\n", x);
auto s = fmt::format(
  std::locale("de_DE.UTF-8"),"{:L}", x);
fmt::print("{}\n", s);
fmt::print("--------------------\n");
std::locale::global(std::locale("de_DE.UTF-8"));
fmt::print("{}\n", x);
fmt::print("{:L}\n", x); 
}
#include <fmt/format.h>
double x = 123.45;
std::locale::global(std::locale("de_DE.UTF-8"));
fmt::print("{}\n", x);
fmt::print("{:L}\n", x);

Does (as of {fmt} v8) not yet work for floating-point numbers and pointers.

#include <array>
#include <iostream>
#include <fmt/ranges.h>

#include <fmt/compile.h>

consteval std::array<char,5> compile_time_itoa (int value) {
  auto result = std::array<char,5>{};
  fmt::format_to(result.data(), FMT_COMPILE("{}"), value);
  return result;
}

int main () {
constexpr auto s = compile_time_itoa(37);
// s = {'3','7',' ',' ',' '}

std::cout << s.data() << '\n';
fmt::print("{}\n", s);
}

fmt::format_args and associated types can be used to pass argument lists to custom formatting functions. This helps to achieve reduced binary code sizes compared to fully parametrized functions.

fmt::vprint(target, fmt::string_view, fmt::format_args)

fmt::vformat(fmt::string_view, fmt::format_args)

fmt::make_format_args(arguments…) fmt::format_arg_store

#include <fmt/format.h>

int main () {
fmt::vprint("{}\n", fmt::make_format_args(47));
fmt::vprint("{} of {}\n", fmt::make_format_args("seven", 9));
}

Example: Formatted HTML Comment Printing

fmt::make_args_checked(str, arguments…) fmt::format_arg_store

  • makes a format_arg_store that contains references to arguments
  • a format_arg_store can be implicitly converted to format_args
  • if str is a compile-time string then its validity is checked at compile time
#include <fmt/format.h>

void vcomment (fmt::string_view format, fmt::format_args args) {
  fmt::print("<-- ");
  fmt::vprint(format, args);
  fmt::print(" -->\n");
}

template <typename Str, typename... Args>
void comment (Str const& format, Args&&... args) {
  vcomment(format, fmt::make_args_checked<Args...>(format, args...));
}

int main () {
  double const d = 12.345;
  comment("{:e} and {}", d, 47);
}
<!-- 1.234500e+01 and 47 -->

format_to(@target, format-string, arguments...)

#include <fmt/format.h>

int main () 
{
double const d = 123.45678;
fmt::memory_buffer buf;
format_to(std::back_inserter(buf), "{:e}", d);

auto ptrToFormattedData  = buf.data();
auto sizeOfFormattedData = buf.size();
fmt::print("{}\n", ptrToFormattedData);
fmt::print("{}\n", sizeOfFormattedData);

auto str = to_string(buf);  // std::string str = "1.234568e+02";
fmt::print("{}\n", str);
}
#include <fmt/ranges.h>
#include <iterator>
#include <vector>

int main () 
{
double const d = 123.45678;

std::vector<char> vc;
fmt::format_to(std::back_inserter(vc), "{:e}", d);
// vc = {'1','.','2','3','4','5','6','8','e','+','0','2'}

fmt::print("{}\n", vc);
fmt::print("{}\n", vc.size());
}

format_to_n(@target, size, format-string, arguments...)

#include <fmt/format.h>
#include <array>

int main () 
{
double const d = 123.45678;
constexpr int N = 15;
std::array<char,N> a;  // initialized with 0s!
fmt::format_to_n(a.data(), N, "{:e}", d);
// a = {'1','.','2','3','4','5','6','8','e','+','0','2',0,0,0}

fmt::print("{}\n", a.data());
}

formatted_size(format-string, arguments...) size of formatted result

#include <fmt/format.h>

int main () 
{
double const d = 123.45678;
auto size = fmt::formatted_size("{:e}", d);  // size = 12

fmt::print("{}", size);
}
  • the allocator will be used for the output container only
  • formatting functions normally don't do any allocations for built-in and string types
#include <string>
#include <memory>
#include <iostream>

#include <fmt/format.h>

// simple allocator that delegates to new/delete
template <class T> 
struct naive_allocator { 
  using value_type = T; 
  template<class U> struct rebind { using other = naive_allocator<U>; };
  T*   allocate(std::size_t n) { return new T[n]; }
  void deallocate(T* p, std::size_t) { delete[] p; } 
};         
using my_allocator = naive_allocator<char>;

// string that uses custom allocator using my_string = std::basic_string< char, std::char_traits<char>, my_allocator>; // format buffer that uses custom allocator using my_buffer = fmt::basic_memory_buffer< char, fmt::inline_buffer_size, my_allocator>;
my_string vformat ( my_allocator alloc, fmt::string_view str, fmt::format_args args) { // temp. buffer for formatting my_buffer buf(alloc); vformat_to(buf, str, args); // result string uses custom allocator return my_string(buf.data(), buf.size(), alloc); } template <typename... Args> my_string format ( my_allocator alloc, fmt::string_view str, Args const&... args) { return vformat(alloc, str, fmt::make_format_args(args...)); }
int main () { my_allocator alloc; auto s = format(alloc, "{} of {}", "seven", 9); // my_string s = "seven of 9"; std::cout << s << '\n'; }

{fmt} – Printing & Formatting

example-based overview of formatting and printing with the {fmt} library

(click for fullscreen view)

Last updated: 2022-12-15

Found this useful? Share it: