What Are the range_format Types in fmtlib? A Complete Guide to C++ Range Formatting

The fmtlib library defines six range_format enumerations—disabled, map, set, sequence, string, and debug_string—in include/fmt/ranges.h that control how C++ ranges, containers, and tuples are serialized during formatting operations.

The fmtlib/fmt library provides comprehensive support for formatting C++ ranges through the range_format enum class. Understanding these range_format types in fmtlib is essential when you need to customize how containers like std::vector, std::map, or character arrays appear in output. Each enumerator instructs the library whether to treat a type as a bracketed sequence, a braced set, a key-value map, or a literal string.

The range_format Enum Declaration

The core range formatting interface is declared in include/fmt/ranges.h at line 31. The enum class range_format provides six distinct formatting strategies that the library uses when encountering iterable types. These enumerations are not manually selected by end users in typical usage; instead, the library's internal trait system determines the appropriate format based on the container's interface.

The Six range_format Types Explained

Each enumerator in range_format determines delimiter choice, element separation, and character escaping behavior.

disabled

Range formatting is turned off. The container is treated as a single opaque object, causing the library to fall back to standard operator<< formatting or custom formatter specializations. Use this mode when you want fmtlib to ignore a container's iterable nature and rely on bespoke output logic.

map

The range is treated as a dictionary-like map containing distinct key_type and mapped_type members. Elements format as key: value pairs wrapped in {} braces. This applies automatically to std::map, std::unordered_map, and user-defined types exposing both type aliases.

set

The range is interpreted as a set-like collection exposing key_type but lacking mapped_type. Elements render as a comma-separated list enclosed in {} braces. std::set and std::unordered_set trigger this mode automatically.

sequence

The generic sequence mode handles any container providing begin() and end() iterators that do not qualify as maps or sets. Elements appear in order within [] brackets. std::vector, std::list, std::deque, and C-style arrays default to this format.

string

Character ranges format as literal strings without surrounding brackets or quotes. std::string, std::vector<char>, and similar character containers print their contents directly using this mode.

debug_string

Similar to string, but each character undergoes debug escaping where non-printable characters convert to \xNN hexadecimal notation. This mode helps visualize hidden bytes in raw buffers or non-ASCII data.

How fmtlib Selects the Format Type

The library determines which range_format enumerator applies by inspecting the type at compile-time through the range_format_kind_ trait, starting at line 253 in include/fmt/ranges.h. This trait checks for map-like interfaces (presence of key_type and mapped_type), then set-like interfaces (key_type only), before falling back to sequence, string, or debug-string rules based on the value type.

Once determined, the range_formatter class defined around line 391 in the same header uses this compile-time constant to emit the appropriate opening delimiter, element separator, and closing delimiter.

Practical Code Examples

The following example demonstrates automatic selection of each range_format type:

#include <fmt/ranges.h>
#include <map>
#include <set>
#include <vector>
#include <string>

int main() {
    std::vector<int> seq   = {1, 2, 3};
    std::set<int> s        = {4, 5, 6};
    std::map<int, char> m  = {{7, 'a'}, {8, 'b'}};
    std::string str        = "hello";

    fmt::print("Sequence : {}\n", seq);        // → [1, 2, 3]
    fmt::print("Set      : {}\n", s);          // → {4, 5, 6}
    fmt::print("Map      : {}\n", m);          // → {7: a, 8: b}
    fmt::print("String   : {}\n", str);        // → hello

    // Debug string (use fmt::debug_string for explicit request)
    fmt::print("Debug    : {}\n", fmt::debug_string(str));
}

Output:


Sequence : [1, 2, 3]
Set      : {4, 5, 6}
Map      : {7: a, 8: b}
String   : hello
Debug    : hello

To explicitly disable range formatting for a specific type, specialize the formatter or provide a custom operator<< implementation that the library will prefer, effectively selecting the disabled mode.

Summary

  • The range_format enum in include/fmt/ranges.h defines six formatting strategies for C++ ranges.
  • map and set use {} delimiters; sequence uses []; string and debug_string omit brackets.
  • The range_format_kind_ trait automatically selects the appropriate format at compile-time based on container interface detection.
  • disabled forces fallback to operator<< or custom formatters.
  • The range_formatter class implements the actual output logic using the selected enumeration.

Frequently Asked Questions

How do I disable range formatting for a specific type in fmtlib?

Provide a custom formatter specialization or an operator<< overload for your type. When the library detects a valid operator<< or custom formatter, it automatically selects the range_format::disabled enumerator, bypassing the generic range formatting logic in include/fmt/ranges.h.

What is the difference between string and debug_string in range_format?

range_format::string prints character ranges literally without escaping, making it ideal for human-readable text. range_format::debug_string escapes non-printable characters as \xNN hexadecimal sequences, which is essential for debugging raw byte buffers or inspecting hidden control characters.

How does fmtlib determine which range_format to use automatically?

The library uses the range_format_kind_ trait defined at line 253 of include/fmt/ranges.h to inspect the type at compile-time. It checks for key_type and mapped_type to identify maps, key_type alone to identify sets, and value type characteristics to distinguish between generic sequences and strings.

Can I force a container to use a specific range_format type?

While the library automatically selects the format via traits, you can influence the behavior by wrapping containers in view types or specializing formatting traits. For explicit debug output, use fmt::debug_string() to force the debug_string format regardless of the automatic selection.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →