What Is the FMT_COMPILE Macro and How to Use It in {fmt}
The FMT_COMPILE macro converts a format string literal into a compile-time parsed representation, eliminating runtime parsing overhead by generating code that directly formats arguments.
The FMT_COMPILE macro is the entry point for {fmt}'s compile-time format string feature in the fmtlib/fmt repository. This optimization moves format string parsing from runtime to compile time, resulting in faster execution and smaller binary sizes for performance-critical applications. When you wrap a string literal with this macro, the library generates specialized formatting code instead of interpreting the format string at runtime.
Understanding the FMT_COMPILE Macro Definition
The FMT_COMPILE macro is defined in [include/fmt/compile.h](https://github.com/fmtlib/fmt/blob/main/include/fmt/compile.h) and serves as the user-facing interface for compile-time formatting. Its implementation depends on your compiler's C++ standard support.
Compiler Requirements and Conditional Definition
The macro uses conditional compilation to detect C++17 capabilities. According to the source code in include/fmt/compile.h (lines 38-40), the definition checks for __cpp_if_constexpr and __cpp_return_type_deduction:
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
# define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::compiled_string)
#else
# define FMT_COMPILE(s) FMT_STRING(s)
#endif
When your compiler supports C++17 if constexpr and return-type deduction, FMT_COMPILE expands to FMT_STRING_IMPL with fmt::compiled_string as the second argument. This creates a compiled string type that encodes the parsed format at compile time. On older compilers, the macro gracefully degrades to FMT_STRING, preserving source compatibility while falling back to runtime parsing.
The Compile-Time Pipeline
Under the hood, FMT_STRING_IMPL (defined in [include/fmt/format.h](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h)) constructs a lightweight wrapper type that marks the literal as a compiled string. This type satisfies the is_compiled_string trait (fmt::detail::is_compiled_string), which overloads in fmt::format detect to trigger the compile-time path (lines 54-57 in compile.h).
When fmt::format receives a compiled string, it invokes detail::compile<T...>(S{}) (around line 554 in compile.h) to produce a templated compile-time format representation. This representation allows the library to emit machine code that writes formatted output directly, bypassing the runtime parser entirely.
How to Use FMT_COMPILE in Your Code
Using the macro requires including the compile-time header and wrapping your format strings. Here is a complete example demonstrating the difference between runtime and compile-time formatting:
#include <fmt/core.h>
#include <fmt/compile.h>
int main() {
// Classic runtime parsing – incurs parsing overhead
std::string a = fmt::format("{} + {}", 1, 2);
// Compile-time parsing – zero runtime format-string work
std::string b = fmt::format(FMT_COMPILE("{} + {}"), 1, 2);
// Both produce "1 + 2", but 'b' executes faster
return 0;
}
The key difference is that FMT_COMPILE("{} + {}") creates a type that encodes the two replacement fields and the literal text " + " at compile time. The resulting binary contains code that directly writes the integer arguments and the separator without interpreting a format string at runtime.
The C++20 _cf Literal Operator
When compiling with C++20 non-type template parameter support (FMT_USE_NONTYPE_TEMPLATE_ARGS), {fmt} provides an even more ergonomic syntax via the user-defined literal _cf:
#include <fmt/compile.h>
using namespace fmt::literals;
int main() {
// Equivalent to FMT_COMPILE("{} + {}")
std::string c = fmt::format("{} + {}"_cf, 1, 2);
}
This literal operator expands to FMT_COMPILE internally, offering cleaner syntax for modern C++ projects. You can check if this feature is available by testing for the FMT_USE_NONTYPE_TEMPLATE_ARGS macro.
Performance Benefits of Compile-Time Formatting
Zero runtime parsing is the primary advantage of using FMT_COMPILE. Standard fmt::format calls must parse the format string, validate arguments against format specifiers, and dispatch to formatting routines at runtime. With FMT_COMPILE, the compiler performs these steps during translation, resulting in:
- Reduced binary size for repeated formatting operations (the format string logic is compiled once per unique format)
- Eliminated branch mispredictions from the format parser
- Inlining opportunities across the formatting boundary
However, because FMT_COMPILE instantiates templates based on the format string contents, it can increase compile times and binary size if used with thousands of unique format strings in the same translation unit.
Summary
FMT_COMPILEis defined ininclude/fmt/compile.hand converts string literals into compile-time parsed format representations.- The macro requires C++17
if constexprsupport for full functionality; otherwise, it degrades toFMT_STRING. - Compiled strings trigger specialized overloads in
fmt::formatthat calldetail::compileto generate direct formatting code. - The
_cfliteral operator provides syntactic sugar for C++20 projects whenFMT_USE_NONTYPE_TEMPLATE_ARGSis enabled. - Use this feature for hot paths where format strings are known at compile time and maximum performance is required.
Frequently Asked Questions
What is the difference between FMT_COMPILE and FMT_STRING?
FMT_STRING validates format strings at compile time but still performs runtime parsing when formatting. FMT_COMPILE goes further by parsing the format string during compilation and generating code that writes output directly without runtime interpretation. FMT_COMPILE produces faster code but requires C++17 features, while FMT_STRING works with older standards.
Does FMT_COMPILE work with dynamic format strings?
No. FMT_COMPILE only accepts string literals known at compile time. If you need to format strings constructed at runtime (such as user input or configuration files), you must use the standard fmt::format runtime interface. Attempting to pass a std::string or const char* variable to FMT_COMPILE will result in a compilation error.
Will using FMT_COMPILE increase my binary size?
It depends on usage patterns. For a few dozen unique format strings, FMT_COMPILE typically reduces binary size by eliminating parser code and runtime format tables. However, because each unique format string instantiates distinct template code, using thousands of different format strings in one translation unit can increase binary size significantly compared to the runtime approach.
Which compilers support full FMT_COMPILE functionality?
Any compiler with C++17 support for if constexpr and return-type deduction enables the full FMT_COMPILE implementation. This includes GCC 7+, Clang 5+, and MSVC 2017+. The macro automatically detects support via the __cpp_if_constexpr and __cpp_return_type_deduction feature test macros and falls back to FMT_STRING behavior on older compilers.
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 →