# How to Format C++ Containers and Tuples with fmtlib

> Learn to format C++ containers and tuples easily with fmtlib. Include <fmt/ranges.h> for automatic comma-separated output enclosed in braces. Simplify your code.

- Repository: [Hello World Foundation/fmt](https://github.com/fmtlib/fmt)
- Tags: how-to-guide
- Published: 2026-09-10

---

**The fmt library provides automatic formatting for STL containers and tuples by including `<fmt/ranges.h>`, which activates specialized formatters that iterate over elements and emit comma-separated values enclosed in braces.**

The fmtlib/fmt repository treats STL-style containers and tuple-like types as first-class formatting objects. By including the range support header, you enable the library to format vectors, maps, tuples, and custom range types without implementing custom `formatter` specializations. This functionality is implemented primarily in [`include/fmt/ranges.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ranges.h) with helper traits defined in [`include/fmt/std.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/std.h).

## Enabling Range and Tuple Support

To format containers and tuples, include the ranges header alongside the core formatting header. The core engine in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) dispatches to specialized formatters defined in [`include/fmt/ranges.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ranges.h) when it detects types satisfying the range or tuple concepts.

```cpp
#include <vector>
#include <map>
#include <tuple>
#include <fmt/ranges.h>  // Required for container and tuple formatting

```

## Formatting STL Containers

In [`include/fmt/ranges.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ranges.h), the **`fmt::detail::range_formatter`** class template provides the generic implementation for container formatting. This formatter detects types with `begin()` and `end()` members satisfying the range concept.

When you pass a container to `fmt::format`, the range formatter iterates over elements and emits them using each element's own formatter, separating values with commas and wrapping the sequence in braces.

```cpp
std::vector<int> v = {1, 2, 3};
fmt::print("vector: {}\n", v);  // → vector: {1, 2, 3}

std::map<std::string, double> m = {{"pi", 3.1415}, {"e", 2.718}};
fmt::print("map: {}\n", m);     // → map: {("e", 2.718), ("pi", 3.1415)}

```

### Format Specifiers for Containers

The **range formatter** accepts standard format specifiers such as width, precision, and alignment. These specifications are forwarded to each element's formatter, allowing fine-grained control while maintaining the container structure.

## Formatting Tuples and Pair-Like Types

Tuple-like types—including `std::tuple`, `std::pair`, and `std::array`—are handled through a separate specialization in [`include/fmt/ranges.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ranges.h). The implementation decomposes tuples at compile time using **`std::tuple_size`** and **`std::get`**, building a list of element formatters via **`detail::tuple::get_formatters`**.

The helper trait **`is_tuple_like`**, defined in [`include/fmt/std.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/std.h), identifies compatible types by checking for valid `std::tuple_size` and `std::tuple_element` specializations.

```cpp
auto tup = std::make_tuple(42, "answer", 3.14);
fmt::print("tuple: {}\n", tup);  // → tuple: {42, answer, 3.14}

```

## Customizing Output with `fmt::join`

For delimiter control without surrounding braces, use **`fmt::join`**, also located in [`include/fmt/ranges.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ranges.h). This utility creates a lightweight view that formats a range using a user-specified separator instead of the default `", "` and omits the braces.

```cpp
fmt::print("joined: {}\n", fmt::join(v, "; "));  // → joined: 1; 2; 3

```

## Summary

- Include `<fmt/ranges.h>` to enable formatting for any STL container or tuple-like type in fmtlib.
- Container formatting is implemented in [`include/fmt/ranges.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ranges.h) by `fmt::detail::range_formatter`, which iterates over elements using `begin()` and `end()`.
- Tuple formatting relies on `std::tuple_size` and `std::get` with helper traits defined in [`include/fmt/std.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/std.h).
- Use `fmt::join` from [`include/fmt/ranges.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ranges.h) for custom separators without surrounding braces.
- Format specifiers apply to individual elements and are processed recursively by the underlying element formatters.

## Frequently Asked Questions

### Why do I get compilation errors when formatting vectors without including `<fmt/ranges.h>`?

The core formatting engine in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) does not register range formatters by default. You must explicitly include [`include/fmt/ranges.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ranges.h) to activate the specializations that handle container iteration and tuple decomposition via `fmt::detail::range_formatter`.

### Can I format custom container types that are not part of the STL?

Yes. If your custom type provides `begin()` and `end()` member functions satisfying the range concept, the formatter in [`include/fmt/ranges.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ranges.h) automatically handles it. For tuple-like custom types, ensure your type works with `std::tuple_size` and `std::tuple_element`, or specialize the `is_tuple_like` trait in [`include/fmt/std.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/std.h).

### How do I remove the braces when printing a container?

Use **`fmt::join`** from [`include/fmt/ranges.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ranges.h) instead of direct formatting. This function returns a view that formats the range with your specified separator while omitting the surrounding braces and commas.

### Does fmtlib support nested containers like vectors of tuples?

Yes. The formatters in [`include/fmt/ranges.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/ranges.h) apply recursively. When encountering nested structures, the library dispatches to `detail::tuple::get_formatters` for tuple components and `range_formatter` for container elements, handling arbitrary nesting depths.