+ By default, ::fast_io::io::print writes to C’s FILE*stdout object.
+ This means the output goes to the standard output stream, just like printf or
+ std::cout, but with safer and faster semantics.
+
+
+ In practice, using fast_io together with stdio or iostream
+ usually does not cause issues. The only problematic cases arise if code calls unusual functions
+ like unput, which can break assumptions because neither stdio nor
+ iostream guarantee consistent behavior for such operations. As long as you avoid
+ those unsafe edge cases, interoperability is fine.
+
+ In fast_io, a manipulator is a helper object that changes how
+ input or output is interpreted or formatted. Instead of relying on unsafe format strings,
+ manipulators make the intent explicit in the type system.
+
+
+ Manipulators are defined in the namespace fast_io::manipulators, which is aliased
+ as fast_io::mnp for convenience. They make input and output safer, more explicit,
+ and more portable than traditional stdio or iostream.
+
+
+ For example:
+
+
+
hex_get(a) — tells scan to read the variable a in hexadecimal.
+
hex(a) — tells println to print a in lowercase hexadecimal.
+
hexupper(a) — prints a in uppercase hexadecimal.
+
base_get<N>(a) — reads a in base N (2 ≤ N ≤ 36).
+
base<N>(a) — prints a in base N.
+
+
+
+
+
Hexadecimal Manipulators
+
+ fast_io provides manipulators to read and print numbers in hexadecimal.
+ hex_get reads input in hex, while hex and hexupper
+ print output in lowercase or uppercase hex respectively:
+
+ fast_io defines a rich set of manipulators to control input and output formatting.
+ For convenience, the namespace fast_io::manipulators is aliased as fast_io::mnp.
+
+
+
base_get<N> — reads numbers in base N (where 2 ≤ N ≤ 36).
+
base<N> — prints numbers in base N.
+
hex — shorthand for base<16>.
+
hexupper — shorthand for base<16,true>, printing hex digits in uppercase.
+
+
+ These manipulators make it easy to work with different numeric bases without relying on unsafe format strings.
+
+ In fast_io, raw pointers and iterators are not printed directly. This is a deliberate
+ safety choice: printing them without explicit intent can lead to undefined or inconsistent
+ behavior across platforms. Instead, fast_io provides a family of pointer‑related
+ manipulators that make the intent explicit and ensure consistent, portable formatting.
+
+
+
+
+
Pointer Manipulators Overview
+
+
pointervw(ptr) — prints the raw address of a pointer in fixed‑width hexadecimal.
+
os_c_str(ptr) — treats a char const* as a C‑string, using strlen or strnlen.
+
funcvw(f) — prints the address of a free function.
+
methodvw(m) — prints member function pointers, including offset information for multiple inheritance.
+
handlevw(h) — prints operating system handles, whether represented as integers (POSIX fd) or pointers (Win32 HANDLE, FILE*).
+
+
+
+
+
Printing Pointers
+
+ Use pointervw to print raw addresses. The format is consistent across platforms:
+ 0x followed by 8 hex digits on 32‑bit systems, or 16 hex digits on 64‑bit systems.
+
+
+#include <fast_io.h>
+
+using namespace fast_io::io;
+
+int main()
+{
+ using namespace fast_io::mnp;
+ int x{42};
+ int *ptr{::std::addressof(x)};
+ println("Address:", pointervw(ptr));
+}
+
+
+
+
+
C‑String Manipulator
+
+ To treat a char const* as a C‑string, use os_c_str. This calls
+ strlen or strnlen depending on overload.
+
+ funcvw prints the address of a free function. methodvw prints member
+ function pointers, including offset information for multiple inheritance cases.
+
+ handlevw is used when printing operating system handles. A handle may be an
+ integer (POSIX file descriptor) or a pointer (Win32 HANDLE, FILE*).
+ handlevw adapts automatically, printing integers directly and pointers in
+ consistent hexadecimal format.
+
+ Pointer‑related manipulators in fast_io make printing low‑level entities explicit,
+ safe, and portable. They cover raw pointers, C‑strings, free functions, member functions,
+ and OS handles. This design avoids the unsafe and inconsistent behavior of
+ stdio and iostream.
+
+ fast_io provides file types such as ibuf_file and obuf_file
+ for buffered input and output. File names can be passed as any character type, and the
+ os_c_str manipulator applies here as well.
+
+
+#include <fast_io.h>
+#include <fast_io_device.h>
+
+int main()
+{
+ ::fast_io::ibuf_file ibf(u8"aplusb_in.txt");
+ ::fast_io::obuf_file obf(u8"aplusb_out.txt");
+ ::std::size_t a, b;
+ scan(ibf, a, b);
+ println(obf, a + b);
+}
+
+
+
+
+
Directory Files
+
+ dir_file represents a directory handle. You can open files relative to a directory
+ using at(dir). This makes it easy to work with subdirectories and ensures
+ portability across platforms.
+
+ native_file_loader uses the operating system’s memory mapping API (if available)
+ to load an entire file into memory. The file is exposed as a contiguous container, allowing
+ iteration and direct access.
+
+
+#include <fast_io.h>
+
+using namespace fast_io::io;
+
+int main(int argc, char **argv)
+{
+ if (argc != 2)
+ {
+ if (argc == 0)
+ {
+ return 1;
+ }
+ perr("Usage: ", fast_io::mnp::os_c_str(*argv), " <file>\n");
+ return 1;
+ }
+ fast_io::native_file_loader loader(::fast_io::mnp::os_c_str(argv[1]));
+ // This will load the entire file into memory through memory mapping.
+ /*
+ This is a contiguous container of the file.
+ You can do things like:
+ std::size_t sum{};
+ for(auto e : loader)
+ sum += e;
+ */
+ print(loader);
+}
+
+ fast_io organizes its file types into six layers. Each layer corresponds to a
+ different level of abstraction, from direct operating system calls up to C and C++ runtime
+ facilities. On top of these file types, fast_io provides operations
+ that unify input and output for all of them through Concepts.
+
+
+
+
+
Hierarchy of File Types
+
From bottom to top:
+
+
wine
+
nt
+
win32
+
posix
+
c
+
filebuf
+
+
+
+
+
Explainations for the Hierarchy of File Types
+
From bottom to top:
+
+
+ wine —
+ ::fast_io::wine_file is the lowest layer used when running Windows binaries on POSIX systems (e.g. Linux, FreeBSD) via Wine. It directly interacts with Wine’s emulated NT kernel APIs.
+
+
+ nt —
+ ::fast_io::nt_file accesses the Windows NT kernel directly via NtWriteFile and related syscalls. This is the most native and lowest-level file interface on modern Windows systems (NT, 2000, XP, 7, 10, etc).
+
+
+ win32 —
+ ::fast_io::win32_file wraps the Win32 API’s WriteFile function via kernel32.dll. It is higher-level than NT and used for compatibility with user-mode Windows applications.
+
+
+ posix —
+ ::fast_io::posix_file wraps POSIX-style file descriptors and maps to write(2) on Unix-like systems. On Windows, it is emulated via MSVCRT or UCRT.
+
+
+ c —
+ ::fast_io::c_file exposes the C standard library’s FILE* interface (e.g. fwrite(3)). It provides buffering and is widely used in legacy C code.
+
+
+ filebuf —
+ ::fast_io::filebuf_file exposes the C++ standard library’s std::filebuf* interface, used by std::fstream. It is the highest-level abstraction and integrates with C++ I/O streams.
+
+
+
+
+
+
Unbuffered Layers
+
+ The first four layers are unbuffered. They map directly to OS APIs and do not
+ add buffering:
+
+
+
::fast_io::wine_file
+
::fast_io::nt_file
+
::fast_io::win32_file
+
::fast_io::posix_file
+
+
+ Each of these also has character type variants, for example:
+
+
+
::fast_io::u8nt_file
+
::fast_io::wwin32_file
+
::fast_io::u32posix_file
+
+
+ These variants allow working with UTF‑8, UTF‑32, or wide character filenames depending
+ on platform conventions.
+
+
+
+
+
Buffered Layers
+
+ The top two layers expose existing buffered facilities provided by the C and C++ runtime
+ libraries:
+
+
+
::fast_io::c_file — exposes C’s FILE* object, which already provides buffering.
+
::fast_io::filebuf_file — exposes C++ std::filebuf, which already provides buffering.
+
+
+ Note: filebuf_file only has ::fast_io::filebuf_file and
+ ::fast_io::wfilebuf_file. Why? Because the C++ standard library never
+ implemented basic functionality for other character types such as
+ ::fast_io::u8filebuf_file. Only narrow and wide character streams are
+ supported.
+
+
+
+
+
Moving Between Layers
+
+ You can construct higher‑level types from lower ones (through std::move), or go
+ back down (through static_cast).
+
+
+// Lower to higher
+::fast_io::nt_file nfl("nt.txt", ::fast_io::open_mode::out);
+print(nfl, "Hello World from nt_file\n");
+
+::fast_io::filebuf_file fbf(std::move(nfl), ::fast_io::open_mode::out);
+print(fbf, "Hello World from filebuf_file\n");
+
+// Higher to lower
+::fast_io::filebuf_file fbf2("fb.txt", ::fast_io::open_mode::out);
+::fast_io::nt_io_observer niob{static_cast<::fast_io::nt_io_observer>(fbf2)};
+print(niob, "Hello World from nt_io_observer\n");
+
+
+
+
+
Observers
+
+ Types like xxx_io_observer are simple aggregates that store a handle. They are
+ trivially copyable, have no destructors, and let you safely pass handles around without
+ ownership semantics.
+
+
+void foo(FILE* fp) {
+ ::fast_io::c_io_observer ciob{fp};
+ print(ciob, "Hello World from c_io_observer\n");
+
+ ::fast_io::nt_io_observer niob{static_cast<::fast_io::nt_io_observer>(ciob)};
+ print(niob, "Hello World from nt_io_observer\n");
+
+ // Inspect native handle
+ print(::fast_io::mnp::handlevw(niob.native_handle()));
+}
+
+
+
+
+
Native File and iobuf_file
+
+ ::fast_io::native_file is an alias to the most appropriate unbuffered file type for
+ the platform:
+