Ch11.3: Manipulators
What Are Manipulators?
A manipulator is a small helper object that wraps a value (or values) and
tells print / println / scan how to
format or parse that value. Instead of format strings like "%x" or
std::hex, fast_io expresses formatting in the type system: the manipulator
is an object with its own type, so the compiler can check and inline it away completely.
All manipulators live in the namespace
::fast_io::manipulators, which has the convenient shorthand
::fast_io::mnp. Most programs just add:
using namespace ::fast_io::mnp;
and then use the manipulators directly. Every example below assumes this using-declaration.
Numeric Bases: hex, oct, bin, dec
The most common manipulators change the base used to print or scan an integer.
hex, oct, bin, and dec produce
lowercase digits. Their uppercase siblings hexupper / octupper /
binupper exist too. For scanning, use the _get variants:
hex_get, oct_get, bin_get, dec_get.
#include <fast_io.h>
using namespace fast_io::io;
int main()
{
::std::size_t n{0xBEEFz};
// Output
println("hex : ", hex(n));
println("oct : ", oct(n));
println("bin : ", bin(n));
println("dec : ", dec(n));
println("hexup : ", hexupper(n));
// Input: read a and b as hexadecimal
::std::size_t a{}, b{};
scan(hex_get(a), hex_get(b));
println("sum = ", hex(a + b));
}
hex0x — Hex With 0x Prefix
hex0x prints an integer in lowercase hexadecimal with the usual
0x prefix. Use hex0xupper for uppercase digits and
0X. These are ideal when producing output that a human will read and
then copy back into source code.
#include <fast_io.h>
using namespace fast_io::io;
int main()
{
::std::size_t flags{0xCAFEz};
// prints: flags = 0xcafe
println("flags = ", hex0x(flags));
// prints: flags = 0XCAFE
println("flags = ", hex0xupper(flags));
}
boolalpha
By default, bool prints as 1 or 0. The
boolalpha manipulator prints it as true / false
instead (or uppercase TRUE / FALSE with the template
argument).
#include <fast_io.h>
using namespace fast_io::io;
int main()
{
bool ok{true};
println("raw : ", ok); // 1
println("alpha : ", boolalpha(ok)); // true
println("alpha up : ", boolalpha<true>(ok)); // TRUE
}
Floating-Point Formats: fixed, scientific, general
Three manipulators control the notation used for floating-point output:
fixed(x)— plain decimal notation, e.g.1234.5678.scientific(x)— scientific notation, e.g.1.2345678e3.general(x)— lets the library choose the shorter form.
Each has a comma_ sibling (comma_fixed,
comma_scientific, comma_general) that inserts thousands
separators. An optional second argument controls the number of digits after the
decimal point.
#include <fast_io.h>
using namespace fast_io::io;
int main()
{
double pi{3.14159265358979};
double big{1234567.875};
println("fixed : ", fixed(pi));
println("scientific : ", scientific(pi));
println("general : ", general(pi));
// Fixed precision: 2 digits after the decimal point
println("fixed(2) : ", fixed(pi, 2zu));
// With thousands separators
println("comma_fixed : ", comma_fixed(big, 2zu));
}
comma_decimal — Thousands Separators
When you only want commas (or other grouping separators) without changing the
floating-point notation, the comma_* family is what you reach for.
comma_decimal is the most common — it formats a number in plain
decimal notation with group separators inserted.
#include <fast_io.h>
using namespace fast_io::io;
int main()
{
::std::size_t population{8110700zu};
// prints something like: 8,110,700
println("people: ", comma_decimal(population));
}
Alignment: left, right, middle
left, right, and middle pad a value to a given
field width. The first argument is the value, the second is the width, and an optional
third argument is the fill character (defaults to space).
#include <fast_io.h>
using namespace fast_io::io;
int main()
{
int n{-42};
// default fill is ' '
println("|", left(n, 10zu), "|"); // | -42 |
println("|", right(n, 10zu), "|"); // | -42 |
println("|", middle(n, 10zu), "|"); // | -42 |
// custom fill character
println("|", left(n, 10zu, '*'), "|"); // | -42*******|
println("|", right(n, 10zu, '0'), "|"); // | 0000000-42|
}
chvw — Print an Integer as a Character
chvw(ch) treats an integral value as a character and prints it.
This is useful when you have a char stored in an integer, or when
you want to print a code point without going through a string.
#include <fast_io.h>
using namespace fast_io::io;
int main()
{
char c{'A'};
// Prints the character A followed by its integer value
println("char = ", chvw(c), " code = ", static_cast<int>(c));
}
rgvw — Range View
rgvw(range, sep) prints every element of a range, separated by the given
string or character. It is the idiomatic way to dump the contents of a container without
writing a loop. The separator may be a C string, a single character, or an
os_c_str-like object.
#include <fast_io.h>
#include <fast_io_dsal/vector.h>
using namespace fast_io::io;
int main()
{
::fast_io::vector<int> v{1, 2, 3, 4, 5};
// prints: 1, 2, 3, 4, 5
println(rgvw(v, ", "));
// Any separator works
// prints: 1 | 2 | 3 | 4 | 5
println(rgvw(v, " | "));
}
addrvw and pointervw
addrvw(p) prints the numeric value of a pointer in full-width hexadecimal
with a 0x prefix — a classic "address" format.
pointervw(p) is similar but aimed at generic pointer-like objects, giving
a clean address-style output. Both work on raw pointers and pointer-like types.
#include <fast_io.h>
using namespace fast_io::io;
int main()
{
int x{42};
int *p{&x};
// prints: &x = 0x00007ffd...
println("&x = ", addrvw(p));
// prints: ptr = 0x00007ffd...
println("ptr = ", pointervw(p));
}
hex_encode — Binary Data as Hex String
hex_encode(first, last) (or the range overload hex_encode(range))
turns a sequence of bytes into a hex string, which is perfect for printing hashes, keys,
or raw buffers. hex_encode_upper produces uppercase letters.
#include <fast_io.h>
#include <fast_io_dsal/vector.h>
using namespace fast_io::io;
int main()
{
::fast_io::vector<::std::uint8_t> digest{
0xDEz, 0xADz, 0xBEz, 0xEFz, 0x01z, 0x23z
};
// prints: deadbeef0123
println(hex_encode(digest));
// prints: DEADBEEF0123
println(hex_encode_upper(digest));
}
ordinal — 1st, 2nd, 3rd…
ordinal(n) prints an integer with its English ordinal suffix:
1st, 2nd, 3rd, 4th,
21st, and so on. Useful for ranking, leaderboards, and dated log messages.
#include <fast_io.h>
using namespace fast_io::io;
int main()
{
for (int i{1}; i <= 5; ++i)
{
// prints: 1st, 2nd, 3rd, 4th, 5th
println(ordinal(i));
}
}
Compound Manipulators: left_width, right_width
Compound manipulators combine multiple formatting operations into a single manipulator
object. left_width and right_width are examples that combine
value formatting with alignment. They are stateless — they apply
only to the value they wrap, with no stream state to corrupt.
left_width(value, width, fill) formats value and left-aligns it
within a field of the given width, padding with fill (defaults to
space). Similarly, right_width(value, width, fill) right-aligns. These are
useful when you want to combine formatting (like hex or fixed)
with alignment in a single, composable expression.
#include <fast_io.h>
using namespace ::fast_io::iomnp;
int main()
{
// Combine hex formatting with left alignment
int value{255};
println("|", left_width(hex(value), 10zu), "|"); // | ff |
println("|", right_width(hex(value), 10zu), "|"); // | ff |
// With custom fill character
println("|", left_width(hex(value), 10zu, '0'), "|"); // | ff00000000|
println("|", right_width(hex(value), 10zu, '*'), "|"); // | ********ff|
// Combine with other manipulators
double pi{3.14159};
println("|", left_width(fixed(pi, 2zu), 15zu), "|"); // | 3.14 |
println("|", right_width(fixed(pi, 2zu), 15zu), "|"); // | 3.14 |
// These are stateless: each manipulator applies only to its value
println(hex(255), " ", 255); // prints: ff 255 (second value is decimal)
}
The key advantage is that these manipulators are stateless. There is no stream state to corrupt, no need to manually restore settings. Each manipulator is a self-contained object that applies only to the value it wraps.
Full Appendix
The manipulators shown above are only the most common ones. The library also
provides base-N I/O (base<N>, base_get<N>),
ISO timestamps, IP address formatting, hex floats, percentage formatters,
transcode manipulators, and more.
For the complete reference, see the Appendix: Manipulators.
Key takeaways
- Manipulators are ordinary objects in
::fast_io::manipulators(shorthand:::fast_io::mnp) that control how values are formatted or parsed. - Base manipulators:
hex,oct,bin,decfor output;hex_get,oct_get,bin_get,dec_getfor input.hex0xadds the0xprefix. boolalphaswitches between1/0andtrue/false.- Floating-point formatting:
fixed,scientific,general, with optional precision andcomma_*variants for thousands separators. - Alignment:
left,right,middletake a value and a field width, plus an optional fill character. chvwprints an integral value as a character;rgvwprints a range with a separator.addrvwandpointervwformat pointers as addresses;hex_encodeturns byte sequences into hex strings.ordinalappends English suffixes.- Compound manipulators:
left_widthandright_widthcombine value formatting with alignment. They are stateless and self-contained. - All manipulators compose with
print,println, andscanin the same way as ordinary values — there is no separate formatting DSL to learn.