|
microfmt
Zero-allocation C++ formatting for constrained environments
|
Opt-in, developer-controlled explicit instantiation of consumer-supplied formatter template instances (e.g. formatter< std::optional<int>>, formatter<reloco::vector<std::string>>) for MICROFMT_SHARED deployments (see microfmt/detail/compat.hpp and microfmt/microfmt_compile.hpp). More...
#include "microfmt.hpp"
Go to the source code of this file.
Macros | |
| #define | MICROFMT_FORMATTER_INSTANCE(...) |
Opt-in, developer-controlled explicit instantiation of consumer-supplied formatter template instances (e.g. formatter< std::optional<int>>, formatter<reloco::vector<std::string>>) for MICROFMT_SHARED deployments (see microfmt/detail/compat.hpp and microfmt/microfmt_compile.hpp).
microfmt_compile.hpp's *.ipp pattern only covers microfmt's own built-in concrete formatters (formatter<semver>, formatter<std::error_code>, ...): microfmt itself defines those types, so it can migrate their definitions to a shared library ahead of time. It cannot do the same for formatter<T> specializations that are themselves templates over a consumer-supplied T (formatter<std::optional<T>>, formatter< reloco::vector<T>>, the type-erased format_type_thunk<T> trampoline, ...) – microfmt has no way to know which T a given application will ever instantiate.
MICROFMT_FORMATTER_INSTANCE(Type) closes that gap by letting the application (not microfmt) declare, once, which concrete Types it wants deduplicated across shared objects the same way – e.g. "every shard .so in my deployment formats std::optional<int> and reloco::vector<std::string>, so pull formatter<T>/format_type_thunk<T> for exactly those two Types into the one common shared library instead of duplicating them into every shard".
Usage: put the same list of MICROFMT_FORMATTER_INSTANCE(...) invocations (after #including whichever formatters/<name>.hpp header defines formatter<Type> for each Type) in one shared header, included by both:
extern template declaration, suppressing that translation unit's own local instantiation and binding it to the shared library's definition above at link time.Keeping both call sites in perfect sync (same Types, same header) is the caller's responsibility: using a Type with microfmt::format_to in a MICROFMT_SHARED consumer without ever listing it here (or listing it here but never linking against a shared library that was actually built with the matching MICROFMT_SHARED_BUILD instantiation) surfaces as an ordinary "undefined reference" link error, not a silent miscompile.
In a plain header-only build (MICROFMT_SHARED not defined at all), this macro expands to nothing: ordinary per-translation-unit implicit instantiation – already deduplicated by the linker's normal vague-linkage handling within a single binary – is exactly what you want, and there is no separate shared object to deduplicate against.
| #define MICROFMT_FORMATTER_INSTANCE | ( | ... | ) |