diff --git a/doc/api.md b/doc/api.md
new file mode 100644
index 00000000..891466a0
--- /dev/null
+++ b/doc/api.md
@@ -0,0 +1,685 @@
+# API Reference {#string-formatting-api}
+
+The {fmt} library API consists of the following parts:
+
+- [`fmt/base.h`](#base-api): the base API providing main formatting functions
+ for `char`/UTF-8 with C++20 compile-time checks and minimal dependencies
+- [`fmt/format.h`](#format-api): the full format API providing additional
+ formatting functions and locale support
+- [`fmt/ranges.h`](#ranges-api): formatting of ranges and tuples
+- [`fmt/chrono.h`](#chrono-api): date and time formatting
+- [`fmt/std.h`](#std-api): formatters for standard library types
+- [`fmt/compile.h`](#compile-api): format string compilation
+- [`fmt/color.h`](#color-api): terminal color and text style
+- [`fmt/os.h`](#os-api): system APIs
+- [`fmt/ostream.h`](#ostream-api): `std::ostream` support
+- [`fmt/args.h`](#args-api): dynamic argument lists
+- [`fmt/printf.h`](#printf-api): `printf` formatting
+- [`fmt/xchar.h`](#xchar-api): optional `wchar_t` support
+
+All functions and types provided by the library reside in namespace `fmt`
+and macros have prefix `FMT_`.
+
+## Base API
+
+`fmt/base.h` defines the base API which provides main formatting functions
+for `char`/UTF-8 with C++20 compile-time checks. It has minimal include
+dependencies for better compile times. This header is only beneficial when
+using {fmt} as a library (the default) and not in the header-only mode.
+It also provides `formatter` specializations for the following types:
+
+- `int`, `unsigned`, `long long`, `unsigned long long`
+- `float`, `double`, `long double`
+- `bool`
+- `char`
+- `const char*`, `fmt::string_view`
+- `const void*`
+
+The following functions use [format string syntax](syntax.md) similar to that
+of [str.format](https://docs.python.org/3/library/stdtypes.html#str.format)
+in Python. They take *fmt* and *args* as arguments.
+
+*fmt* is a format string that contains literal text and replacement fields
+surrounded by braces `{}`. The fields are replaced with formatted arguments
+in the resulting string. [\~fmt::format_string]{.title-ref} is a format string
+which can be implicitly constructed from a string literal or a `constexpr`
+string and is checked at compile time in C++20. To pass a runtime format
+string wrap it in [fmt::runtime]{.title-ref}.
+
+*args* is an argument list representing objects to be formatted.
+
+I/O errors are reported as [`std::system_error`](
+https://en.cppreference.com/w/cpp/error/system_error) exceptions unless
+specified otherwise.
+
+
+::: print(format_string, T&&...)
+
+::: vprint(string_view, format_args)
+
+::: print(FILE*, format_string, T&&...)
+
+::: vprint(FILE*, string_view, format_args)
+
+::: println(format_string, T&&...)
+
+::: println(FILE*, format_string, T&&...)
+
+::: format_to(OutputIt&&, format_string, T&&...)
+
+::: format_to_n(OutputIt, size_t, format_string, T&&...)
+
+::: formatted_size(format_string, T&&...)
+
+::: format_to_n_result
+
+### Compile-Time Format String Checks
+
+Compile-time format string checks are enabled by default on compilers
+that support C++20 `consteval`. On older compilers you can use the
+`FMT_STRING `{.interpreted-text role="ref"}: macro
+defined in `fmt/format.h` instead.
+
+Unused arguments are allowed as in Python's `str.format` and ordinary functions.
+
+::: basic_format_string
+
+:: {.doxygentypedef}
+fmt::format_string
+::
+
+::: runtime(string_view)
+
+### Formatting User-Defined Types {#udt}
+
+The {fmt} library provides formatters for many standard C++ types.
+See [`fmt/ranges.h`](#ranges-api) for ranges and tuples including standard
+containers such as `std::vector`, [`fmt/chrono.h`](#chrono-api) for date and
+time formatting and [`fmt/std.h`](#std-api) for other standard library types.
+
+There are two ways to make a user-defined type formattable: providing a
+`format_as` function or specializing the `formatter` struct template.
+
+Use `format_as` if you want to make your type formattable as some other
+type with the same format specifiers. The `format_as` function should
+take an object of your type and return an object of a formattable type.
+It should be defined in the same namespace as your type.
+
+Example ([run](https://godbolt.org/z/nvME4arz8)):
+
+ #include
+
+ namespace kevin_namespacy {
+ enum class film {
+ house_of_cards, american_beauty, se7en = 7
+ };
+ auto format_as(film f) { return fmt::underlying(f); }
+ }
+
+ int main() {
+ fmt::print("{}\n", kevin_namespacy::film::se7en); // prints "7"
+ }
+
+Using specialization is more complex but gives you full control over
+parsing and formatting. To use this method specialize the `formatter`
+struct template for your type and implement `parse` and `format`
+methods.
+
+The recommended way of defining a formatter is by reusing an existing
+one via inheritance or composition. This way you can support standard
+format specifiers without implementing them yourself. For example:
+
+ // color.h:
+ #include
+
+ enum class color {red, green, blue};
+
+ template <> struct fmt::formatter: formatter {
+ // parse is inherited from formatter.
+
+ auto format(color c, format_context& ctx) const
+ -> format_context::iterator;
+ };
+
+ // color.cc:
+ #include "color.h"
+ #include
+
+ auto fmt::formatter::format(color c, format_context& ctx) const
+ -> format_context::iterator {
+ string_view name = "unknown";
+ switch (c) {
+ case color::red: name = "red"; break;
+ case color::green: name = "green"; break;
+ case color::blue: name = "blue"; break;
+ }
+ return formatter::format(name, ctx);
+ }
+
+Note that `formatter::format` is defined in `fmt/format.h`
+so it has to be included in the source file. Since `parse` is inherited
+from `formatter` it will recognize all string format
+specifications, for example
+
+``` c++
+fmt::format("{:>10}", color::blue)
+```
+
+will return `" blue"`.
+
+The experimental `nested_formatter` provides an easy way of applying a
+formatter to one or more subobjects.
+
+For example:
+
+ #include
+
+ struct point {
+ double x, y;
+ };
+
+ template <>
+ struct fmt::formatter : nested_formatter {
+ auto format(point p, format_context& ctx) const {
+ return write_padded(ctx, [=](auto out) {
+ return format_to(out, "({}, {})", this->nested(p.x),
+ this->nested(p.y));
+ });
+ }
+ };
+
+ int main() {
+ fmt::print("[{:>20.2f}]", point{1, 2});
+ }
+
+prints:
+
+ [ (1.00, 2.00)]
+
+Notice that fill, align and width are applied to the whole object which
+is the recommended behavior while the remaining specifiers apply to
+elements.
+
+In general the formatter has the following form:
+
+ template <> struct fmt::formatter {
+ // Parses format specifiers and stores them in the formatter.
+ //
+ // [ctx.begin(), ctx.end()) is a, possibly empty, character range that
+ // contains a part of the format string starting from the format
+ // specifications to be parsed, e.g. in
+ //
+ // fmt::format("{:f} continued", ...);
+ //
+ // the range will contain "f} continued". The formatter should parse
+ // specifiers until '}' or the end of the range. In this example the
+ // formatter should parse the 'f' specifier and return an iterator
+ // pointing to '}'.
+ constexpr auto parse(format_parse_context& ctx)
+ -> format_parse_context::iterator;
+
+ // Formats value using the parsed format specification stored in this
+ // formatter and writes the output to ctx.out().
+ auto format(const T& value, format_context& ctx) const
+ -> format_context::iterator;
+ };
+
+It is recommended to at least support fill, align and width that apply
+to the whole object and have the same semantics as in standard
+formatters.
+
+You can also write a formatter for a hierarchy of classes:
+
+ // demo.h:
+ #include
+ #include
+
+ struct A {
+ virtual ~A() {}
+ virtual std::string name() const { return "A"; }
+ };
+
+ struct B : A {
+ virtual std::string name() const { return "B"; }
+ };
+
+ template
+ struct fmt::formatter::value, char>> :
+ fmt::formatter {
+ auto format(const A& a, format_context& ctx) const {
+ return fmt::formatter::format(a.name(), ctx);
+ }
+ };
+
+ // demo.cc:
+ #include "demo.h"
+ #include
+
+ int main() {
+ B b;
+ A& a = b;
+ fmt::print("{}", a); // prints "B"
+ }
+
+Providing both a `formatter` specialization and a `format_as` overload
+is disallowed.
+
+### Named Arguments
+
+::: arg(const Char*, const T&)
+
+Named arguments are not supported in compile-time checks at the moment.
+
+### Argument Lists
+
+You can create your own formatting function with compile-time checks and
+small binary footprint, for example ():
+
+``` c++
+#include
+
+void vlog(const char* file, int line, fmt::string_view format,
+ fmt::format_args args) {
+ fmt::print("{}: {}: ", file, line);
+ fmt::vprint(format, args);
+}
+
+template
+void log(const char* file, int line, fmt::format_string format, T&&... args) {
+ vlog(file, line, format, fmt::make_format_args(args...));
+}
+
+#define MY_LOG(format, ...) log(__FILE__, __LINE__, format, __VA_ARGS__)
+
+MY_LOG("invalid squishiness: {}", 42);
+```
+
+Note that `vlog` is not parameterized on argument types which improves
+compile times and reduces binary code size compared to a fully
+parameterized version.
+
+::: make_format_args(T&...)
+
+::: basic_format_args
+
+:: {.doxygentypedef}
+fmt::format_args
+::
+
+:: {.doxygenclass members=""}
+fmt::basic_format_arg
+::
+
+:: {.doxygenclass members=""}
+fmt::basic_format_parse_context
+::
+
+:: {.doxygenclass members=""}
+fmt::context
+::
+
+:: {.doxygentypedef}
+fmt::format_context
+::
+
+### Dynamic Argument Lists {#args-api}
+
+The header `fmt/args.h` provides `dynamic_format_arg_store`, a
+builder-like API that can be used to construct format argument lists
+dynamically.
+
+:: {.doxygenclass members=""}
+fmt::dynamic_format_arg_store
+::
+
+### Compatibility
+
+:: {.doxygenclass members=""}
+fmt::basic_string_view
+::
+
+:: {.doxygentypedef}
+fmt::string_view
+::
+
+## Format API
+
+`fmt/format.h` defines the full format API providing additional
+formatting functions and locale support.
+
+
+::: format(format_string, T&&...)
+
+::: vformat(string_view, format_args)
+
+### Literal-Based API
+
+The following user-defined literals are defined in `fmt/format.h`.
+
+::: operator""_a()
+
+### Utilities
+
+::: ptr(T)
+
+::: underlying(Enum)
+
+::: to_string(const T&)
+
+::: group_digits(T)
+
+:: {.doxygenclass members=""}
+fmt::detail::buffer
+::
+
+::: basic_memory_buffer
+
+### System Errors
+
+{fmt} does not use `errno` to communicate errors to the user, but it may
+call system functions which set `errno`. Users should not make any
+assumptions about the value of `errno` being preserved by library
+functions.
+
+::: system_error
+
+::: format_system_error
+
+### Custom Allocators
+
+The {fmt} library supports custom dynamic memory allocators. A custom
+allocator class can be specified as a template argument to
+`fmt::basic_memory_buffer`{.interpreted-text role="class"}:
+
+ using custom_memory_buffer =
+ fmt::basic_memory_buffer;
+
+It is also possible to write a formatting function that uses a custom
+allocator:
+
+ using custom_string =
+ std::basic_string, custom_allocator>;
+
+ custom_string vformat(custom_allocator alloc, fmt::string_view format_str,
+ fmt::format_args args) {
+ auto buf = custom_memory_buffer(alloc);
+ fmt::vformat_to(std::back_inserter(buf), format_str, args);
+ return custom_string(buf.data(), buf.size(), alloc);
+ }
+
+ template
+ inline custom_string format(custom_allocator alloc,
+ fmt::string_view format_str,
+ const Args& ... args) {
+ return vformat(alloc, format_str, fmt::make_format_args(args...));
+ }
+
+The allocator will be used for the output container only. Formatting
+functions normally don\'t do any allocations for built-in and string
+types except for non-default floating-point formatting that occasionally
+falls back on `sprintf`.
+
+### Locale
+
+All formatting is locale-independent by default. Use the `'L'` format
+specifier to insert the appropriate number separator characters from the
+locale:
+
+ #include
+ #include
+
+ std::locale::global(std::locale("en_US.UTF-8"));
+ auto s = fmt::format("{:L}", 1000000); // s == "1,000,000"
+
+`fmt/format.h` provides the following overloads of formatting functions
+that take `std::locale` as a parameter. The locale type is a template
+parameter to avoid the expensive `` include.
+
+::: format(const Locale&, format_string, T&&...)
+
+::: format_to(OutputIt, const Locale&, format_string, T&&...)
+
+::: formatted_size(const Locale&, format_string, T&&...)
+
+### Legacy Compile-Time Format String Checks {#legacy-checks}
+
+`FMT_STRING` enables compile-time checks on older compilers. It requires
+C++14 or later and is a no-op in C++11.
+
+:: {.doxygendefine}
+FMT_STRING
+::
+
+To force the use of legacy compile-time checks, define the preprocessor
+variable `FMT_ENFORCE_COMPILE_STRING`. When set, functions accepting
+`FMT_STRING` will fail to compile with regular strings.
+
+## Range and Tuple Formatting {#ranges-api}
+
+The library also supports convenient formatting of ranges and tuples:
+
+ #include
+
+ std::tuple t{'a', 1, 2.0f};
+ // Prints "('a', 1, 2.0)"
+ fmt::print("{}", t);
+
+Using `fmt::join`, you can separate tuple elements with a custom
+separator:
+
+ #include
+
+ std::tuple t = {1, 'a'};
+ // Prints "1, a"
+ fmt::print("{}", fmt::join(t, ", "));
+
+::: join(Range&&, string_view)
+
+::: join(It, Sentinel, string_view)
+
+## Date and Time Formatting {#chrono-api}
+
+`fmt/chrono.h` provides formatters for
+
+- [std::chrono::duration](https://en.cppreference.com/w/cpp/chrono/duration)
+- [std::chrono::time_point](https://en.cppreference.com/w/cpp/chrono/time_point)
+- [std::tm](https://en.cppreference.com/w/cpp/chrono/c/tm)
+
+The format syntax is described in [Chrono Format Specifications](syntax.md#
+chrono-format-specifications).
+
+**Example**:
+
+ #include
+
+ int main() {
+ std::time_t t = std::time(nullptr);
+
+ // Prints "The date is 2020-11-07." (with the current date):
+ fmt::print("The date is {:%Y-%m-%d}.", fmt::localtime(t));
+
+ using namespace std::literals::chrono_literals;
+
+ // Prints "Default format: 42s 100ms":
+ fmt::print("Default format: {} {}\n", 42s, 100ms);
+
+ // Prints "strftime-like format: 03:15:30":
+ fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
+ }
+
+::: localtime(std::time_t)
+
+::: gmtime(std::time_t)
+
+## Standard Library Types Formatting {#std-api}
+
+`fmt/std.h` provides formatters for:
+
+- [`std::atomic`](https://en.cppreference.com/w/cpp/atomic/atomic)
+- [`std::atomic_flag`](https://en.cppreference.com/w/cpp/atomic/atomic_flag)
+- [`std::bitset`](https://en.cppreference.com/w/cpp/utility/bitset)
+- [`std::error_code`](https://en.cppreference.com/w/cpp/error/error_code)
+- [`std::filesystem::path`](https://en.cppreference.com/w/cpp/filesystem/path)
+- [`std::monostate`](https://en.cppreference.com/w/cpp/utility/variant/monostate)
+- [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional)
+- [`std::source_location`](https://en.cppreference.com/w/cpp/utility/source_location)
+- [`std::thread::id`](https://en.cppreference.com/w/cpp/thread/thread/id)
+- [`std::variant`](https://en.cppreference.com/w/cpp/utility/variant/variant)
+
+::: ptr(const std::unique_ptr&)
+
+::: ptr(const std::shared_ptr&)
+
+### Formatting Variants
+
+A `std::variant` is only formattable if every variant alternative is
+formattable, and requires the `__cpp_lib_variant` [library
+feature](https://en.cppreference.com/w/cpp/feature_test).
+
+**Example**:
+
+ #include
+
+ std::variant v0{'x'};
+ // Prints "variant('x')"
+ fmt::print("{}", v0);
+
+ std::variant v1;
+ // Prints "variant(monostate)"
+
+## Format String Compilation {#compile-api}
+
+`fmt/compile.h` provides format string compilation enabled via the
+`FMT_COMPILE` macro or the `_cf` user-defined literal. Format strings
+marked with `FMT_COMPILE` or `_cf` are parsed, checked and converted
+into efficient formatting code at compile-time. This supports arguments
+of built-in and string types as well as user-defined types with `format`
+functions taking the format context type as a template parameter in
+their `formatter` specializations. For example:
+
+ template <> struct fmt::formatter {
+ constexpr auto parse(format_parse_context& ctx);
+
+ template
+ auto format(const point& p, FormatContext& ctx) const;
+ };
+
+Format string compilation can generate more binary code compared to the
+default API and is only recommended in places where formatting is a
+performance bottleneck.
+
+:: {.doxygendefine}
+FMT_COMPILE
+::
+
+::: operator""_cf
+
+## Terminal Color and Text Style {#color-api}
+
+`fmt/color.h` provides support for terminal color and text style output.
+
+::: print(const text_style&, format_string, T&&...)
+
+::: fg(detail::color_type)
+
+:: {.doxygenfunction}
+bg(detail::color_type)
+::
+
+:: {.doxygenfunction}
+styled(const T& value, text_style ts)
+::
+
+## System APIs {#os-api}
+
+:: {.doxygenclass members=""}
+fmt::ostream
+::
+
+:: {.doxygenfunction}
+fmt::windows_error
+::
+
+## `std::ostream` Support {#ostream-api}
+
+`fmt/ostream.h` provides `std::ostream` support including formatting of
+user-defined types that have an overloaded insertion operator
+(`operator<<`). In order to make a type formattable via `std::ostream`
+you should provide a `formatter` specialization inherited from
+`ostream_formatter`:
+
+ #include
+
+ struct date {
+ int year, month, day;
+
+ friend std::ostream& operator<<(std::ostream& os, const date& d) {
+ return os << d.year << '-' << d.month << '-' << d.day;
+ }
+ };
+
+ template <> struct fmt::formatter : ostream_formatter {};
+
+ std::string s = fmt::format("The date is {}", date{2012, 12, 9});
+ // s == "The date is 2012-12-9"
+
+:: {.doxygenfunction}
+streamed(const T &)
+::
+
+:: {.doxygenfunction}
+print(std::ostream &os, format_string\ fmt, T&&\... args)
+::
+
+## `printf` Formatting {#printf-api}
+
+The header `fmt/printf.h` provides `printf`-like formatting
+functionality. The following functions use [printf format string
+syntax](https://pubs.opengroup.org/onlinepubs/009695399/functions/fprintf.html)
+with the POSIX extension for positional arguments. Unlike their standard
+counterparts, the `fmt` functions are type-safe and throw an exception
+if an argument type doesn\'t match its format specification.
+
+:: {.doxygenfunction}
+printf(string_view fmt, const T&\... args) -\> int
+::
+
+:: {.doxygenfunction}
+fprintf(std::FILE \*f, const S &fmt, const T&\... args) -\> int
+::
+
+:: {.doxygenfunction}
+sprintf(const S&, const T&\...)
+::
+
+## `wchar_t` Support {#xchar-api}
+
+The optional header `fmt/xchar.h` provides support for `wchar_t` and
+exotic character types.
+
+:: {.doxygenstruct}
+fmt::is_char
+::
+
+:: {.doxygentypedef}
+fmt::wstring_view
+::
+
+:: {.doxygentypedef}
+fmt::wformat_context
+::
+
+:: {.doxygenfunction}
+fmt::to_wstring(const T &value)
+::
+
+## Compatibility with C++20 `std::format`
+
+{fmt} implements nearly all of the [C++20 formatting
+library](https://en.cppreference.com/w/cpp/utility/format) with the
+following differences:
+
+- Names are defined in the `fmt` namespace instead of `std` to avoid
+ collisions with standard library implementations.
+- Width calculation doesn\'t use grapheme clusterization. The latter has
+ been implemented in a separate branch but hasn\'t been integrated yet.
diff --git a/doc/api.rst b/doc/api.rst
deleted file mode 100644
index e132bd26..00000000
--- a/doc/api.rst
+++ /dev/null
@@ -1,688 +0,0 @@
-.. _string-formatting-api:
-
-*************
-API Reference
-*************
-
-The {fmt} library API consists of the following parts:
-
-* :ref:`fmt/base.h `: the base API providing main formatting functions
- for ``char``/UTF-8 with C++20 compile-time checks and minimal dependencies
-* :ref:`fmt/format.h `: the full format API providing additional
- formatting functions and locale support
-* :ref:`fmt/ranges.h `: formatting of ranges and tuples
-* :ref:`fmt/chrono.h `: date and time formatting
-* :ref:`fmt/std.h `: formatters for standard library types
-* :ref:`fmt/compile.h `: format string compilation
-* :ref:`fmt/color.h `: terminal color and text style
-* :ref:`fmt/os.h `: system APIs
-* :ref:`fmt/ostream.h `: ``std::ostream`` support
-* :ref:`fmt/args.h `: dynamic argument lists
-* :ref:`fmt/printf.h `: ``printf`` formatting
-* :ref:`fmt/xchar.h `: optional ``wchar_t`` support
-
-All functions and types provided by the library reside in namespace ``fmt`` and
-macros have prefix ``FMT_``.
-
-.. _base-api:
-
-Base API
-========
-
-``fmt/base.h`` defines the base API which provides main formatting functions
-for ``char``/UTF-8 with C++20 compile-time checks. It has minimal include
-dependencies for better compile times. This header is only beneficial when
-using {fmt} as a library (the default) and not in the header-only mode.
-It also provides ``formatter`` specializations for the following types:
-
-* ``int``, ``unsigned``, ``long long``, ``unsigned long long``
-* ``float``, ``double``, ``long double``
-* ``bool``
-* ``char``
-* ``const char*``, ``fmt::string_view``
-* ``const void*``
-
-The following functions use :ref:`format string syntax `
-similar to that of Python's `str.format
-`_.
-They take *fmt* and *args* as arguments.
-
-*fmt* is a format string that contains literal text and replacement fields
-surrounded by braces ``{}``. The fields are replaced with formatted arguments
-in the resulting string. `~fmt::format_string` is a format string which can be
-implicitly constructed from a string literal or a ``constexpr`` string and is
-checked at compile time in C++20. To pass a runtime format string wrap it in
-`fmt::runtime`.
-
-*args* is an argument list representing objects to be formatted.
-
-I/O errors are reported as `std::system_error
-`_ exceptions unless
-specified otherwise.
-
-.. _print:
-
-.. doxygenfunction:: fmt::print(format_string fmt, T&&... args)
-.. doxygenfunction:: fmt::vprint(string_view fmt, format_args args)
-
-.. doxygenfunction:: print(FILE *f, format_string fmt, T&&... args)
-.. doxygenfunction:: vprint(FILE *f, string_view fmt, format_args args)
-
-.. doxygenfunction:: println(format_string fmt, T&&... args)
-.. doxygenfunction:: println(FILE *f, format_string fmt, T&&... args)
-
-.. _format:
-
-.. doxygenfunction:: format_to(OutputIt&& out, format_string fmt, T&&... args) -> remove_cvref_t
-.. doxygenfunction:: format_to_n(OutputIt out, size_t n, format_string fmt, T&&... args) -> format_to_n_result
-.. doxygenfunction:: formatted_size(format_string fmt, T&&... args) -> size_t
-
-.. doxygenstruct:: fmt::format_to_n_result
- :members:
-
-Compile-Time Format String Checks
----------------------------------
-
-Compile-time format string checks are enabled by default on compilers
-that support C++20 ``consteval``. On older compilers you can use the
-:ref:`FMT_STRING `: macro defined in ``fmt/format.h`` instead.
-
-Unused arguments are allowed as in Python's `str.format` and ordinary functions.
-
-.. doxygenclass:: fmt::basic_format_string
- :members:
-
-.. doxygentypedef:: fmt::format_string
-
-.. doxygenfunction:: fmt::runtime(string_view) -> runtime_format_string<>
-
-.. _udt:
-
-Formatting User-Defined Types
------------------------------
-
-The {fmt} library provides formatters for many standard C++ types.
-See :ref:`fmt/ranges.h ` for ranges and tuples including standard
-containers such as ``std::vector``, :ref:`fmt/chrono.h ` for date
-and time formatting and :ref:`fmt/std.h ` for other standard library
-types.
-
-There are two ways to make a user-defined type formattable: providing a
-``format_as`` function or specializing the ``formatter`` struct template.
-
-Use ``format_as`` if you want to make your type formattable as some other type
-with the same format specifiers. The ``format_as`` function should take an
-object of your type and return an object of a formattable type. It should be
-defined in the same namespace as your type.
-
-Example (https://godbolt.org/z/nvME4arz8)::
-
- #include
-
- namespace kevin_namespacy {
- enum class film {
- house_of_cards, american_beauty, se7en = 7
- };
- auto format_as(film f) { return fmt::underlying(f); }
- }
-
- int main() {
- fmt::print("{}\n", kevin_namespacy::film::se7en); // prints "7"
- }
-
-Using specialization is more complex but gives you full control over parsing and
-formatting. To use this method specialize the ``formatter`` struct template for
-your type and implement ``parse`` and ``format`` methods.
-
-The recommended way of defining a formatter is by reusing an existing one via
-inheritance or composition. This way you can support standard format specifiers
-without implementing them yourself. For example::
-
- // color.h:
- #include
-
- enum class color {red, green, blue};
-
- template <> struct fmt::formatter: formatter {
- // parse is inherited from formatter.
-
- auto format(color c, format_context& ctx) const
- -> format_context::iterator;
- };
-
- // color.cc:
- #include "color.h"
- #include
-
- auto fmt::formatter::format(color c, format_context& ctx) const
- -> format_context::iterator {
- string_view name = "unknown";
- switch (c) {
- case color::red: name = "red"; break;
- case color::green: name = "green"; break;
- case color::blue: name = "blue"; break;
- }
- return formatter::format(name, ctx);
- }
-
-Note that ``formatter::format`` is defined in ``fmt/format.h`` so
-it has to be included in the source file. Since ``parse`` is inherited from
-``formatter`` it will recognize all string format specifications,
-for example
-
-.. code-block:: c++
-
- fmt::format("{:>10}", color::blue)
-
-will return ``" blue"``.
-
-The experimental ``nested_formatter`` provides an easy way of applying a
-formatter to one or more subobjects.
-
-For example::
-
- #include
-
- struct point {
- double x, y;
- };
-
- template <>
- struct fmt::formatter : nested_formatter {
- auto format(point p, format_context& ctx) const {
- return write_padded(ctx, [=](auto out) {
- return format_to(out, "({}, {})", this->nested(p.x),
- this->nested(p.y));
- });
- }
- };
-
- int main() {
- fmt::print("[{:>20.2f}]", point{1, 2});
- }
-
-prints::
-
- [ (1.00, 2.00)]
-
-Notice that fill, align and width are applied to the whole object which is the
-recommended behavior while the remaining specifiers apply to elements.
-
-In general the formatter has the following form::
-
- template <> struct fmt::formatter {
- // Parses format specifiers and stores them in the formatter.
- //
- // [ctx.begin(), ctx.end()) is a, possibly empty, character range that
- // contains a part of the format string starting from the format
- // specifications to be parsed, e.g. in
- //
- // fmt::format("{:f} continued", ...);
- //
- // the range will contain "f} continued". The formatter should parse
- // specifiers until '}' or the end of the range. In this example the
- // formatter should parse the 'f' specifier and return an iterator
- // pointing to '}'.
- constexpr auto parse(format_parse_context& ctx)
- -> format_parse_context::iterator;
-
- // Formats value using the parsed format specification stored in this
- // formatter and writes the output to ctx.out().
- auto format(const T& value, format_context& ctx) const
- -> format_context::iterator;
- };
-
-It is recommended to at least support fill, align and width that apply to the
-whole object and have the same semantics as in standard formatters.
-
-You can also write a formatter for a hierarchy of classes::
-
- // demo.h:
- #include
- #include
-
- struct A {
- virtual ~A() {}
- virtual std::string name() const { return "A"; }
- };
-
- struct B : A {
- virtual std::string name() const { return "B"; }
- };
-
- template
- struct fmt::formatter::value, char>> :
- fmt::formatter {
- auto format(const A& a, format_context& ctx) const {
- return fmt::formatter::format(a.name(), ctx);
- }
- };
-
- // demo.cc:
- #include "demo.h"
- #include
-
- int main() {
- B b;
- A& a = b;
- fmt::print("{}", a); // prints "B"
- }
-
-Providing both a ``formatter`` specialization and a ``format_as`` overload is
-disallowed.
-
-Named Arguments
----------------
-
-.. doxygenfunction:: fmt::arg(const S&, const T&)
-
-Named arguments are not supported in compile-time checks at the moment.
-
-Argument Lists
---------------
-
-You can create your own formatting function with compile-time checks and small
-binary footprint, for example (https://godbolt.org/z/vajfWEG4b):
-
-.. code:: c++
-
- #include
-
- void vlog(const char* file, int line, fmt::string_view format,
- fmt::format_args args) {
- fmt::print("{}: {}: ", file, line);
- fmt::vprint(format, args);
- }
-
- template
- void log(const char* file, int line, fmt::format_string format, T&&... args) {
- vlog(file, line, format, fmt::make_format_args(args...));
- }
-
- #define MY_LOG(format, ...) log(__FILE__, __LINE__, format, __VA_ARGS__)
-
- MY_LOG("invalid squishiness: {}", 42);
-
-Note that ``vlog`` is not parameterized on argument types which improves compile
-times and reduces binary code size compared to a fully parameterized version.
-
-.. doxygenfunction:: make_format_args(T&... args)
-
-.. doxygenclass:: fmt::basic_format_args
- :members:
-
-.. doxygentypedef:: fmt::format_args
-
-.. doxygenclass:: fmt::basic_format_arg
- :members:
-
-.. doxygenclass:: fmt::basic_format_parse_context
- :members:
-
-.. doxygenclass:: fmt::context
- :members:
-
-.. doxygentypedef:: fmt::format_context
-
-.. _args-api:
-
-Dynamic Argument Lists
-----------------------
-
-The header ``fmt/args.h`` provides ``dynamic_format_arg_store``, a builder-like
-API that can be used to construct format argument lists dynamically.
-
-.. doxygenclass:: fmt::dynamic_format_arg_store
- :members:
-
-Compatibility
--------------
-
-.. doxygenclass:: fmt::basic_string_view
- :members:
-
-.. doxygentypedef:: fmt::string_view
-
-.. _format-api:
-
-Format API
-==========
-
-``fmt/format.h`` defines the full format API providing additional formatting
-functions and locale support.
-
-.. doxygenfunction:: format(format_string fmt, T&&... args) -> std::string
-.. doxygenfunction:: vformat(string_view fmt, format_args args) -> std::string
-
-Literal-Based API
------------------
-
-The following user-defined literals are defined in ``fmt/format.h``.
-
-.. doxygenfunction:: operator""_a()
-
-Utilities
----------
-
-.. doxygenfunction:: fmt::ptr(T p) -> const void*
-.. doxygenfunction:: fmt::ptr(const std::unique_ptr &p) -> const void*
-.. doxygenfunction:: fmt::ptr(const std::shared_ptr &p) -> const void*
-
-.. doxygenfunction:: fmt::underlying(Enum e) -> typename std::underlying_type::type
-
-.. doxygenfunction:: fmt::to_string(const T &value) -> std::string
-
-.. doxygenfunction:: fmt::group_digits(T value) -> group_digits_view
-
-.. doxygenclass:: fmt::detail::buffer
- :members:
-
-.. doxygenclass:: fmt::basic_memory_buffer
- :protected-members:
- :members:
-
-System Errors
--------------
-
-{fmt} does not use ``errno`` to communicate errors to the user, but it may call
-system functions which set ``errno``. Users should not make any assumptions
-about the value of ``errno`` being preserved by library functions.
-
-.. doxygenfunction:: fmt::system_error
-
-.. doxygenfunction:: fmt::format_system_error
-
-Custom Allocators
------------------
-
-The {fmt} library supports custom dynamic memory allocators.
-A custom allocator class can be specified as a template argument to
-:class:`fmt::basic_memory_buffer`::
-
- using custom_memory_buffer =
- fmt::basic_memory_buffer;
-
-It is also possible to write a formatting function that uses a custom
-allocator::
-
- using custom_string =
- std::basic_string, custom_allocator>;
-
- custom_string vformat(custom_allocator alloc, fmt::string_view format_str,
- fmt::format_args args) {
- auto buf = custom_memory_buffer(alloc);
- fmt::vformat_to(std::back_inserter(buf), format_str, args);
- return custom_string(buf.data(), buf.size(), alloc);
- }
-
- template
- inline custom_string format(custom_allocator alloc,
- fmt::string_view format_str,
- const Args& ... args) {
- return vformat(alloc, format_str, fmt::make_format_args(args...));
- }
-
-The allocator will be used for the output container only. Formatting functions
-normally don't do any allocations for built-in and string types except for
-non-default floating-point formatting that occasionally falls back on
-``sprintf``.
-
-Locale
-------
-
-All formatting is locale-independent by default. Use the ``'L'`` format
-specifier to insert the appropriate number separator characters from the
-locale::
-
- #include
- #include
-
- std::locale::global(std::locale("en_US.UTF-8"));
- auto s = fmt::format("{:L}", 1000000); // s == "1,000,000"
-
-``fmt/format.h`` provides the following overloads of formatting functions that
-take ``std::locale`` as a parameter. The locale type is a template parameter to
-avoid the expensive ```` include.
-
-.. doxygenfunction:: format(const Locale& loc, format_string fmt, T&&... args) -> std::string
-.. doxygenfunction:: format_to(OutputIt out, const Locale& loc, format_string fmt, T&&... args) -> OutputIt
-.. doxygenfunction:: formatted_size(const Locale& loc, format_string fmt, T&&... args) -> size_t
-
-.. _legacy-checks:
-
-Legacy Compile-Time Format String Checks
-----------------------------------------
-
-``FMT_STRING`` enables compile-time checks on older compilers. It requires C++14
-or later and is a no-op in C++11.
-
-.. doxygendefine:: FMT_STRING
-
-To force the use of legacy compile-time checks, define the preprocessor variable
-``FMT_ENFORCE_COMPILE_STRING``. When set, functions accepting ``FMT_STRING``
-will fail to compile with regular strings.
-
-.. _ranges-api:
-
-Range and Tuple Formatting
-==========================
-
-The library also supports convenient formatting of ranges and tuples::
-
- #include
-
- std::tuple t{'a', 1, 2.0f};
- // Prints "('a', 1, 2.0)"
- fmt::print("{}", t);
-
-Using ``fmt::join``, you can separate tuple elements with a custom separator::
-
- #include
-
- std::tuple t = {1, 'a'};
- // Prints "1, a"
- fmt::print("{}", fmt::join(t, ", "));
-
-.. doxygenfunction:: fmt::join(Range &&range, string_view sep) -> join_view
-.. doxygenfunction:: fmt::join(It begin, Sentinel end, string_view sep) -> join_view
-
-.. _chrono-api:
-
-Date and Time Formatting
-========================
-
-``fmt/chrono.h`` provides formatters for
-
-* `std::chrono::duration `_
-* `std::chrono::time_point
- `_
-* `std::tm `_
-
-The format syntax is described in :ref:`chrono-specs`.
-
-**Example**::
-
- #include
-
- int main() {
- std::time_t t = std::time(nullptr);
-
- // Prints "The date is 2020-11-07." (with the current date):
- fmt::print("The date is {:%Y-%m-%d}.", fmt::localtime(t));
-
- using namespace std::literals::chrono_literals;
-
- // Prints "Default format: 42s 100ms":
- fmt::print("Default format: {} {}\n", 42s, 100ms);
-
- // Prints "strftime-like format: 03:15:30":
- fmt::print("strftime-like format: {:%H:%M:%S}\n", 3h + 15min + 30s);
- }
-
-.. doxygenfunction:: localtime(std::time_t time)
-
-.. doxygenfunction:: gmtime(std::time_t time) -> std::tm
-
-.. _std-api:
-
-Standard Library Types Formatting
-=================================
-
-``fmt/std.h`` provides formatters for:
-
-* `std::atomic `_
-* `std::atomic_flag `_
-* `std::bitset `_
-* `std::error_code `_
-* `std::filesystem::path `_
-* `std::monostate `_
-* `std::optional `_
-* `std::source_location `_
-* `std::thread::id `_
-* `std::variant `_
-
-Formatting Variants
--------------------
-
-A ``std::variant`` is only formattable if every variant alternative is formattable, and requires the
-``__cpp_lib_variant`` `library feature `_.
-
-**Example**::
-
- #include
-
- std::variant v0{'x'};
- // Prints "variant('x')"
- fmt::print("{}", v0);
-
- std::variant v1;
- // Prints "variant(monostate)"
-
-.. _compile-api:
-
-Format String Compilation
-=========================
-
-``fmt/compile.h`` provides format string compilation enabled via the
-``FMT_COMPILE`` macro or the ``_cf`` user-defined literal. Format strings
-marked with ``FMT_COMPILE`` or ``_cf`` are parsed, checked and converted into
-efficient formatting code at compile-time. This supports arguments of built-in
-and string types as well as user-defined types with ``format`` functions taking
-the format context type as a template parameter in their ``formatter``
-specializations. For example::
-
- template <> struct fmt::formatter {
- constexpr auto parse(format_parse_context& ctx);
-
- template
- auto format(const point& p, FormatContext& ctx) const;
- };
-
-Format string compilation can generate more binary code compared to the default
-API and is only recommended in places where formatting is a performance
-bottleneck.
-
-.. doxygendefine:: FMT_COMPILE
-
-.. doxygenfunction:: operator""_cf()
-
-.. _color-api:
-
-Terminal Color and Text Style
-=============================
-
-``fmt/color.h`` provides support for terminal color and text style output.
-
-.. doxygenfunction:: print(const text_style &ts, format_string fmt, T&&... args)
-
-.. doxygenfunction:: fg(detail::color_type)
-
-.. doxygenfunction:: bg(detail::color_type)
-
-.. doxygenfunction:: styled(const T& value, text_style ts)
-
-.. _os-api:
-
-System APIs
-===========
-
-.. doxygenclass:: fmt::ostream
- :members:
-
-.. doxygenfunction:: fmt::windows_error
-
-.. _ostream-api:
-
-``std::ostream`` Support
-========================
-
-``fmt/ostream.h`` provides ``std::ostream`` support including formatting of
-user-defined types that have an overloaded insertion operator (``operator<<``).
-In order to make a type formattable via ``std::ostream`` you should provide a
-``formatter`` specialization inherited from ``ostream_formatter``::
-
- #include
-
- struct date {
- int year, month, day;
-
- friend std::ostream& operator<<(std::ostream& os, const date& d) {
- return os << d.year << '-' << d.month << '-' << d.day;
- }
- };
-
- template <> struct fmt::formatter : ostream_formatter {};
-
- std::string s = fmt::format("The date is {}", date{2012, 12, 9});
- // s == "The date is 2012-12-9"
-
-.. doxygenfunction:: streamed(const T &)
-
-.. doxygenfunction:: print(std::ostream &os, format_string fmt, T&&... args)
-
-.. _printf-api:
-
-``printf`` Formatting
-=====================
-
-The header ``fmt/printf.h`` provides ``printf``-like formatting functionality.
-The following functions use `printf format string syntax
-`_ with
-the POSIX extension for positional arguments. Unlike their standard
-counterparts, the ``fmt`` functions are type-safe and throw an exception if an
-argument type doesn't match its format specification.
-
-.. doxygenfunction:: printf(string_view fmt, const T&... args) -> int
-
-.. doxygenfunction:: fprintf(std::FILE *f, const S &fmt, const T&... args) -> int
-
-.. doxygenfunction:: sprintf(const S&, const T&...)
-
-.. _xchar-api:
-
-``wchar_t`` Support
-===================
-
-The optional header ``fmt/xchar.h`` provides support for ``wchar_t`` and exotic
-character types.
-
-.. doxygenstruct:: fmt::is_char
-
-.. doxygentypedef:: fmt::wstring_view
-
-.. doxygentypedef:: fmt::wformat_context
-
-.. doxygenfunction:: fmt::to_wstring(const T &value)
-
-Compatibility with C++20 ``std::format``
-========================================
-
-{fmt} implements nearly all of the `C++20 formatting library
-`_ with the following
-differences:
-
-* Names are defined in the ``fmt`` namespace instead of ``std`` to avoid
- collisions with standard library implementations.
-* Width calculation doesn't use grapheme clusterization. The latter has been
- implemented in a separate branch but hasn't been integrated yet.
-* Most C++20 chrono types are not supported yet.