Ch11.12.2: Complete <iomanip> Reference

The <iomanip> header provides manipulators that take arguments. These manipulators modify the stream’s internal state, which persists until explicitly changed. This is a fundamental design flaw — see “Why C++ iostream Is Fundamentally Flawed” in Ch11.12. fast_io’s manipulators are stateless and do not suffer from these issues.

Field Width and Fill

Manipulator Description Example
std::setw(n) Set minimum field width to n characters std::cout << std::setw(10) << 42;
std::setfill(c) Set fill character to c std::cout << std::setfill('0') << std::setw(5) << 42;

Warning: std::setw only applies to the next output operation, then resets to 0. This is inconsistent and error-prone.


#include <iostream>
#include <iomanip>

int main() {
    std::cout << std::setw(10) << 42 << '\n';  //         42
    std::cout << 42 << '\n';  // 42 (width reset!)

    std::cout << std::setfill('0') << std::setw(5) << 42 << '\n';  // 00042
    return 0;
}

Numeric Base

Manipulator Description Example
std::setbase(n) Set numeric base to n (8, 10, or 16) std::cout << std::setbase(16) << 255; (prints ff)

#include <iostream>
#include <iomanip>

int main() {
    std::cout << std::setbase(16) << 255 << '\n';  // ff
    std::cout << std::setbase(8) << 255 << '\n';   // 377
    std::cout << std::setbase(10) << 255 << '\n';  // 255
    return 0;
}

Precision

Manipulator Description Example
std::setprecision(n) Set floating-point precision to n digits std::cout << std::setprecision(3) << 3.14159; (prints 3.14)

Note: Precision persists until changed. Combined with std::fixed or std::scientific, it controls decimal places.


#include <iostream>
#include <iomanip>

int main() {
    double pi = 3.14159;
    std::cout << std::setprecision(3) << pi << '\n';  // 3.14
    std::cout << pi << '\n';  // 3.14 (precision persists!)

    std::cout << std::fixed << std::setprecision(2) << pi << '\n';  // 3.14
    std::cout << std::scientific << std::setprecision(4) << pi << '\n';  // 3.1416e+00
    return 0;
}

Other Manipulators

Manipulator Description
std::resetiosflags(f) Clear specified format flags
std::setiosflags(f) Set specified format flags

Format flags include: std::ios::left, std::ios::right, std::ios::internal, std::ios::dec, std::ios::hex, std::ios::oct, std::ios::fixed, std::ios::scientific, std::ios::boolalpha, std::ios::showbase, std::ios::showpoint, std::ios::showpos, std::ios::skipws, std::ios::uppercase, std::ios::unitbuf.


#include <iostream>
#include <iomanip>

int main() {
    // Set flags
    std::cout << std::setiosflags(std::ios::hex | std::ios::showbase);
    std::cout << 255 << '\n';  // 0xff

    // Reset flags
    std::cout << std::resetiosflags(std::ios::hex);
    std::cout << std::setiosflags(std::ios::dec);
    std::cout << 255 << '\n';  // 255

    return 0;
}

Why This Is Terrible

All of these manipulators modify the stream’s internal state. Consider:


#include <iostream>
#include <iomanip>

void print_hex(int value) {
    std::cout << std::hex << value << '\n';
    // Stream is now in hex mode!
}

int main() {
    print_hex(255);  // Prints "ff"
    std::cout << 255 << '\n';  // Also prints "ff"!
    // Must manually restore: std::cout << std::dec;
}

This is a maintenance nightmare. You must remember to restore the stream state after every use, or else later code will behave unexpectedly. Exceptions can leave the stream in an inconsistent state. Multiple threads can corrupt each other’s formatting.

fast_io’s manipulators are stateless:


#include <fast_io.h>

void print_hex(int value) {
    using namespace ::fast_io::iomnp;
    println(::fast_io::mnp::hex(value));
    // No state to restore!
}

int main() {
    using namespace ::fast_io::iomnp;
    print_hex(255);  // Prints "ff"
    println(255);    // Prints "255" (decimal, as expected)
}

Each manipulator applies only to the value it wraps. There is no global state to corrupt.