Formatting Support

Boost.int128 support formatting with both <format> (when C++20 and the header are both available), and <fmt/format.h> The following modifiers are listed in order of how they should be specified in the format string to be valid, and all information applies for both <format> and <fmt/format.h>

Fill and Alignment

You can specify alignment with an optional fill character. The format is [[fill]align] where:

Alignment

Effect

<

Left-aligns the value within the available space

>

Right-aligns the value within the available space

^

Centers the value within the available space

The optional fill character (default is space) appears before the alignment character.

Examples:

Format

Output for 42

{:<6d}

"42 " (left-aligned with spaces)

{:>6d}

" 42" (right-aligned with spaces)

{:^6d}

" 42 " (centered with spaces)

{:*<6d}

"42**" (left-aligned with asterisks)

{:0>6d}

"000042" (right-aligned with zeros)

{:*^6d}

"42" (centered with asterisks)

When no alignment is specified but a width is given (e.g., {:6d}), zero-padding is applied from the left.

Sign

There are three allowable sings first in the format string:

Sign

Effect

+

Adds a + to positive values, and a - to negative values

-

Only adds a - to negative values

` ` (Space)

Adds a ` ` to positive values, and a - to negative values. Preserves alignment

Padding

You can then add any number of padding characters to make sure that a formatted value takes up a specified width (5 means minimum width of 5 characters and so on). Any integer value is accepted here.

Prepend Prefix

If you want to prepend the prefix to your number (if applicable) add #

Output Base

Effect

Binary

0b or 0B

Octal

O

Decimal

None

Hex

0x or 0X

Output Base Modifiers

The following type modifiers are the same as those used by built-in integer values

Modifier

Format

b, B

Binary

o

Octal

d

Decimal

x, X

Hex

When the uppercase modifier is used all characters will be capitalized (e.g. 0x2a vs 0X2A)

Default

The default format string {} will output the same as {:-d}, that is a decimal value which only has a sign if negative.

<format>

Examples using all of the above modifiers in some permutation:

#include <boost/int128.hpp>
#include <format>
#include <iostream>

int main()
{
    constexpr boost::int128::int128_t value {42};

    // Default format
    std::cout << std::format("{}", value) << '\n'; // Outputs: 42

    // Sign modifier
    std::cout << std::format("{:+d}", value) << '\n'; // Outputs +42
    std::cout << std::format("{:+d}", -value) << '\n'; // Outputs -42

    // Alignment with fill characters
    std::cout << std::format("{:<10d}", value) << '\n';  // Outputs "42        " (left-aligned)
    std::cout << std::format("{:>10d}", value) << '\n';  // Outputs "        42" (right-aligned)
    std::cout << std::format("{:^10d}", value) << '\n';  // Outputs "    42    " (centered)
    std::cout << std::format("{:*<10d}", value) << '\n'; // Outputs "42********" (left, fill with *)
    std::cout << std::format("{:0>10d}", value) << '\n'; // Outputs "0000000042" (right, fill with 0)
    std::cout << std::format("{:*^10d}", value) << '\n'; // Outputs "****42****" (centered, fill with *)

    // Alignment with sign
    std::cout << std::format("{:>+10d}", value) << '\n'; // Outputs "       +42"
    std::cout << std::format("{:<+10d}", value) << '\n'; // Outputs "+42       "

    // Output base modifier and Prefix
    std::cout << std::format("{:x}", value) << '\n'; // Outputs 2a
    std::cout << std::format("{:X}", value) << '\n'; // Outputs 2A
    std::cout << std::format("{:#X}", value) << '\n'; // Outputs 0X2A

    // Alignment with hex and prefix
    std::cout << std::format("{:>#10x}", value) << '\n';  // Outputs "      0x2a"
    std::cout << std::format("{:<#10x}", value) << '\n';  // Outputs "0x2a      "
    std::cout << std::format("{:*^#10x}", value) << '\n'; // Outputs "***0x2a***"

    // Zero-padding (no alignment specified)
    std::cout << std::format("{:#10X}", value) << '\n'; // Outputs 0X00000002A

    return 0;
}

{fmt}

This is nearly the same as above but with fmt::format in place of std::format:

#include <boost/int128.hpp>
#include <fmt/format.h>
#include <iostream>

int main()
{
    constexpr boost::int128::int128_t value {42};

    // Default format
    std::cout << fmt::format("{}", value) << '\n'; // Outputs: 42

    // Sign modifier
    std::cout << fmt::format("{:+d}", value) << '\n'; // Outputs +42
    std::cout << fmt::format("{:+d}", -value) << '\n'; // Outputs -42

    // Alignment with fill characters
    std::cout << fmt::format("{:<10d}", value) << '\n';  // Outputs "42        " (left-aligned)
    std::cout << fmt::format("{:>10d}", value) << '\n';  // Outputs "        42" (right-aligned)
    std::cout << fmt::format("{:^10d}", value) << '\n';  // Outputs "    42    " (centered)
    std::cout << fmt::format("{:*<10d}", value) << '\n'; // Outputs "42********" (left, fill with *)
    std::cout << fmt::format("{:0>10d}", value) << '\n'; // Outputs "0000000042" (right, fill with 0)
    std::cout << fmt::format("{:*^10d}", value) << '\n'; // Outputs "****42****" (centered, fill with *)

    // Alignment with sign
    std::cout << fmt::format("{:>+10d}", value) << '\n'; // Outputs "       +42"
    std::cout << fmt::format("{:<+10d}", value) << '\n'; // Outputs "+42       "

    // Output base modifier and Prefix
    std::cout << fmt::format("{:x}", value) << '\n'; // Outputs 2a
    std::cout << fmt::format("{:X}", value) << '\n'; // Outputs 2A
    std::cout << fmt::format("{:#X}", value) << '\n'; // Outputs 0X2A

    // Alignment with hex and prefix
    std::cout << fmt::format("{:>#10x}", value) << '\n';  // Outputs "      0x2a"
    std::cout << fmt::format("{:<#10x}", value) << '\n';  // Outputs "0x2a      "
    std::cout << fmt::format("{:*^#10x}", value) << '\n'; // Outputs "***0x2a***"

    // Zero-padding (no alignment specified)
    std::cout << fmt::format("{:#10X}", value) << '\n'; // Outputs 0X00000002A

    return 0;
}