Minimal Three-File Configuration for fmtlib: Using base.h, format.h, and format-inl.h
The minimal three-file configuration for fmtlib consists of base.h, format.h, and format-inl.h, providing a complete header-only subset of the library with full formatting capabilities.
The {fmt} library (https://github.com/fmtlib/fmt) is typically distributed as a comprehensive formatting toolkit, but it can be reduced to just three essential headers for projects requiring a lightweight, self-contained solution. This minimal three-file configuration delivers the complete public API and core implementation without external dependencies.
The Three Core Files
The fmtlib source code is organized into modular headers, but these three specific files contain everything required for standard formatting tasks.
base.h – The Foundation
Located at include/fmt/base.h, this header defines the low-level infrastructure that the entire library builds upon. It contains compile-time feature detection macros, fundamental type utilities, and the fmt namespace scaffolding.
Key components in base.h include:
- Version and configuration macros:
FMT_VERSION,FMT_CONSTEXPR, and compiler capability detection - Type traits:
enable_if_t,remove_cvref_t, anduint128for internal arithmetic - Namespace guards:
FMT_BEGIN_NAMESPACEandFMT_END_NAMESPACEwrappers that ensure proper encapsulation across different compiler environments
This file establishes the metaprogramming foundation required by the formatting engine but contains no actual formatting logic.
format.h – The Public API
The include/fmt/format.h header declares the user-facing interface, including fmt::format, fmt::format_to, fmt::print, and the basic_string_view implementation. It provides the compile-time format string checking through the format_string template and defines the format_error exception class.
Critical declarations in this header include:
- Formatting functions:
format,format_to, andprintoverloads - String view:
basic_string_viewimplementation (with fallback support for pre-C++17 standards) - Context types: Forward declarations of
formatter,parse_context, and format specifiers
Importantly, format.h contains only declarations and lightweight templates, ensuring fast compilation when included in translation units that do not require the heavy implementation details.
format-inl.h – The Implementation
The include/fmt/format-inl.h header provides the actual implementation of everything declared in format.h. This separation allows the heavy numeric conversion code to be compiled once and reused, mimicking the traditional single-translation-unit approach while maintaining header-only flexibility.
This file contains:
- Core routines:
do_format_decimal,format_decimal, anddo_format_base2efor integer formatting - Floating-point conversion: The Dragonbox algorithm implementation and cache tables for high-performance decimal conversions
- Utilities:
assert_fail, locale handling functions, memory allocation helpers (detail::allocate), andreport_errorfor throwingformat_errorexceptions
Because format.h includes format-inl.h at the end of the translation unit, you obtain the complete implementation without separate compilation steps.
Complete Working Example
To use the minimal three-file configuration, copy base.h, format.h, and format-inl.h into a fmt/ directory and include them in your source:
#include "fmt/base.h"
#include "fmt/format.h"
#include "fmt/format-inl.h"
#include <string>
int main() {
// Direct output using fmt::print
fmt::print("Hello, {}! The answer is {}.\n", "world", 42);
// String formatting with precision control
std::string s = fmt::format("Pi ≈ {:.3f}", 3.1415926535);
// s now holds "Pi ≈ 3.142"
return 0;
}
This configuration supports all standard formatting features, including positional arguments, width and precision specifiers, and type-safe formatting for built-in types.
Why This Configuration Works
The separation of concerns across these three files enables the minimal three-file configuration to function as a complete formatting library:
-
base.hsupplies the compile-time machinery and type traits required by the template-heavy API, ensuring compatibility across C++11 through C++23 standards. -
format.hexposes only the public interface, keeping compile times minimal for files that merely call formatting functions without needing the implementation details. -
format-inl.hencapsulates the heavy lifting—numeric conversions, locale handling, and memory management—allowing the compiler to optimize these routines across translation units while maintaining header-only deployment flexibility.
All other files in the fmtlib repository (such as ostream.h, printf.h, chrono.h, and xchar.h) are optional extensions built atop this foundation. They provide additional functionality for formatting standard library types, wide characters, or C-style printf compatibility, but are not required for core string formatting operations.
Summary
- The minimal three-file configuration for fmtlib requires only
base.h,format.h, andformat-inl.hfrom theinclude/fmt/directory. base.hprovides compiler detection, type traits, and namespace infrastructure ininclude/fmt/base.h.format.hdeclares the public API includingfmt::format,fmt::print, andformat_stringininclude/fmt/format.h.format-inl.hcontains the Dragonbox floating-point implementation and core formatting logic ininclude/fmt/format-inl.h.- This configuration creates a header-only library subset suitable for embedded systems or vendored dependencies without CMake configuration.
Frequently Asked Questions
Can I use fmtlib with just format.h without base.h and format-inl.h?
No, format.h depends on definitions in base.h for type traits (remove_cvref_t), macros (FMT_CONSTEXPR), and namespace guards. Additionally, without format-inl.h, you will encounter linker errors for undefined implementations of do_format_decimal and Dragonbox conversion routines. All three files are required for a functional minimal configuration.
Does the three-file configuration support floating-point formatting?
Yes, format-inl.h includes the complete Dragonbox algorithm implementation and cache tables necessary for high-performance, correctly rounded floating-point decimal conversions. The format_decimal and do_format_base2e functions handle all IEEE-754 floating-point types without requiring additional headers from the full repository.
How does this minimal configuration affect compile times compared to the full library?
The three-file configuration generally improves compile times for translation units that only need the formatting API because format.h remains lightweight and declaration-focused. The heavy template instantiation and numeric conversion code reside in format-inl.h, which can be included in a single implementation file or precompiled header, while other files include only the lightweight format.h declarations.
Is the minimal three-file configuration compatible with C++11?
Yes, according to the source code in include/fmt/base.h, the library uses feature detection macros to provide fallbacks for pre-C++17 features like string_view. The basic_string_view implementation in format.h and the constexpr utilities in base.h are designed to function across C++11, C++14, C++17, and later standards, making this configuration suitable for legacy codebases.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →