# How to Iterate Over YAML Sequences and Maps in yaml-cpp: A Complete Guide

> Learn to iterate over YAML sequences and maps in yaml-cpp using C++ iterators and range-based for loops. Traverse YAML documents efficiently.

- Repository: [Jesse Beder/yaml-cpp](https://github.com/jbeder/yaml-cpp)
- Tags: how-to-guide
- Published: 2026-07-11

---

**yaml-cpp provides a standard C++ iterator interface via `YAML::Node::begin()` and `end()` that yields `YAML::Node` references for sequences and `std::pair`-like `iterator_value` objects for maps, allowing range-based for loops and STL algorithms to traverse YAML documents naturally.**

The `yaml-cpp` library parses YAML documents into a tree of `YAML::Node` objects. Whether you're processing configuration files or data pipelines, understanding how to traverse **sequences** (arrays) and **maps** (dictionaries) efficiently is essential for robust C++ applications. This guide explains the iterator architecture implemented in the `jbeder/yaml-cpp` repository and provides practical examples for iterating over YAML nodes.

## Understanding the Iterator Architecture

According to the `yaml-cpp` source code, the iteration mechanism relies on a template-based foundation that abstracts the differences between sequence and map traversal. The public API exposes familiar `begin()` and `end()` methods on `YAML::Node` objects, but the underlying implementation distinguishes between node types through the `detail::iterator_base<V>` template.

In [`include/yaml-cpp/node/node.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/node.h), the `YAML::Node` class declares `begin()` and `end()` methods that return forward iterators. These methods instantiate `iterator_base<detail::iterator_value>`, defined in [`include/yaml-cpp/node/detail/iterator_fwd.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/detail/iterator_fwd.h) via the type aliases `YAML::iterator` and `YAML::const_iterator`.

The core implementation resides in [`include/yaml-cpp/node/detail/iterator.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/detail/iterator.h). Here, the `iterator_base` template implements the forward-iterator requirements, while [`include/yaml-cpp/node/iterator.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/iterator.h) defines `detail::iterator_value`. This struct inherits from `Node` but exposes `first` and `second` members (representing key and value) when iterating over maps.

### How `iterator_value` Handles Node Types

When dereferencing an iterator, the `operator*` implementation (found in `detail::iterator_base`) constructs an `iterator_value` based on the underlying node structure:

- **For sequences**: The iterator yields a `Node` representing the element at that index.
- **For maps**: The iterator yields an `iterator_value` where `first` contains the key node and `second` contains the value node.

This design allows the same C++ iteration syntax to work seamlessly across both data structures.

## Code Examples for yaml-cpp Iteration

### Iterating Over a Sequence

When processing a YAML sequence (e.g., `[1, 2, 3]`), each dereferenced iterator returns a `YAML::Node` representing the scalar or complex element at that position:

```cpp
YAML::Node root = YAML::Load("[1, 2, 3]");
for (const YAML::Node& elem : root) {          // elem is a Node
    std::cout << elem.as<int>() << '\n';
}

```

The `elem` variable is a `Node` object, allowing direct conversion to native C++ types via `as<T>()`.

### Iterating Over a Map

For YAML maps (e.g., `{a: 10, b: 20}`), the iterator returns a `detail::iterator_value` that exposes `first` (the key) and `second` (the value) as `Node` references:

```cpp
YAML::Node root = YAML::Load("{a: 10, b: 20, c: 30}");
for (const YAML::Node& entry : root) {        // entry is iterator_value
    const YAML::Node& key   = entry.first;    // key node
    const YAML::Node& value = entry.second;   // value node
    std::cout << key.Scalar() << ": " << value.as<int>() << '\n';
}

```

Because `iterator_value` inherits from `Node`, you can use `entry` directly where a `Node` is expected, but accessing `first` and `second` is required to separate keys from values.

### Using STL Algorithms

The forward-iterator implementation in `yaml-cpp` supports standard C++ algorithms. You can pass `map.begin()` and `map.end()` to functions like `std::accumulate`:

```cpp
YAML::Node map = YAML::Load("{x: 5, y: 7, z: 2}");
int sum = std::accumulate(map.begin(), map.end(), 0,
    [](int acc, const YAML::Node& pair) {
        return acc + pair.second.as<int>();   // pair.second is the value
    });
std::cout << "Sum = " << sum << '\n';

```

This works because `map.end()` returns a valid sentinel iterator and dereferenced iterators expose the `second` member for value access.

### Const vs. Mutable Iterators

The library provides both mutable and const iterators via [`iterator_fwd.h`](https://github.com/jbeder/yaml-cpp/blob/main/iterator_fwd.h). Use `const YAML::Node&` for read-only access or `YAML::Node&` to modify values in place:

```cpp
YAML::Node mutableRoot = YAML::Load("[10, 20]");
for (YAML::Node& n : mutableRoot) {   // mutable reference
    n = n.as<int>() * 2;              // modify in-place
}

```

The `begin()` and `end()` methods return appropriate iterator types based on the const-qualification of the `YAML::Node` instance.

## Key Source Files in yaml-cpp

Understanding the iterator implementation requires examining these specific files in the `jbeder/yaml-cpp` repository:

- **[`include/yaml-cpp/node/node.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/node.h)**: Declares the `YAML::Node` class and the public `begin()`/`end()` API that returns forward iterators.
- **[`include/yaml-cpp/node/detail/iterator_fwd.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/detail/iterator_fwd.h)**: Defines the `iterator` and `const_iterator` type aliases that map to `iterator_base<detail::iterator_value>`.
- **[`include/yaml-cpp/node/detail/iterator.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/detail/iterator.h)**: Contains the template implementation of `iterator_base<V>`, which manages the underlying `node_iterator` and constructs `iterator_value` objects during dereference.
- **[`include/yaml-cpp/node/iterator.h`](https://github.com/jbeder/yaml-cpp/blob/main/include/yaml-cpp/node/iterator.h)**: Defines `detail::iterator_value`, the struct that represents both sequence elements and map entries (via `first`/`second` members) while inheriting `Node` behavior.

## Summary

- **yaml-cpp** exposes standard forward iterators via `YAML::Node::begin()` and `end()`, supporting range-based for loops and STL algorithms.
- **Sequence iteration** yields `YAML::Node` objects directly, allowing immediate conversion to C++ types.
- **Map iteration** yields `detail::iterator_value` objects with `first` (key) and `second` (value) members to access paired data.
- The implementation supports both **const and mutable** access patterns, enabling read-only traversal or in-place modification.
- Core iterator logic resides in [`node.h`](https://github.com/jbeder/yaml-cpp/blob/main/node.h), [`iterator_fwd.h`](https://github.com/jbeder/yaml-cpp/blob/main/iterator_fwd.h), and the [`detail/iterator.h`](https://github.com/jbeder/yaml-cpp/blob/main/detail/iterator.h) implementation files.

## Frequently Asked Questions

### What is the difference between `YAML::iterator` and `YAML::const_iterator`?

`YAML::iterator` (defined in [`iterator_fwd.h`](https://github.com/jbeder/yaml-cpp/blob/main/iterator_fwd.h)) allows modification of the underlying `YAML::Node` elements during iteration, while `YAML::const_iterator` provides read-only access. The `begin()` and `end()` methods return the appropriate type based on the const-qualification of the node. For mutable nodes, use `YAML::Node& elem` in your loop; for const nodes, use `const YAML::Node& elem`.

### How do I check if a YAML node is a sequence or map before iterating?

Use the `IsSequence()` or `IsMap()` methods on the `YAML::Node` object before entering the loop. For example:

```cpp
if (node.IsSequence()) {
    for (const auto& elem : node) { /* sequence logic */ }
} else if (node.IsMap()) {
    for (const auto& pair : node) { /* map logic using pair.first/second */ }
}

```

This prevents runtime errors when accessing `first` or `second` on sequence nodes that don't expose those members.

### Can I modify YAML values while iterating over a map?

Yes, if you use a non-const iterator. Declare your loop variable as `YAML::Node& entry` (instead of `const YAML::Node& entry`), then assign to `entry.second` to update the value. Note that you cannot modify the key (`entry.first`) during iteration, as this would violate the map's structural integrity. For sequences, you can modify the element directly via the loop reference.

### What type does the iterator dereference operator return for sequences vs maps?

According to the implementation in [`detail/iterator.h`](https://github.com/jbeder/yaml-cpp/blob/main/detail/iterator.h), the dereference operator returns a `detail::iterator_value` in both cases. However, for **sequences**, this object behaves like a single `YAML::Node` representing the element. For **maps**, the same struct exposes `first` and `second` members containing the key and value nodes respectively. This unified interface allows the same iteration syntax to work for both node types while providing map-specific accessors when needed.