# How to Preserve and Emit YAML Comments in yaml-cpp: A Complete Guide

> Learn how to preserve and emit YAML comments using yaml-cpp. This guide explains why comments are discarded by default and how to reinsert them with the YAML::Comment helper.

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

---

**yaml-cpp parses comments during scanning but discards them immediately—they are not stored in the node tree, so you must explicitly emit comments using the `YAML::Comment` helper and the emitter API.**

The yaml-cpp library is a popular C++ parser and emitter for YAML files. While it handles the data structure perfectly, many developers are surprised to discover that **comments are not preserved after parsing**. If you need to retain or generate comments in your output, you must understand how to emit them manually using the library's emitter API. This guide explains how to preserve and emit YAML comments in yaml-cpp based on the actual source code implementation in the jbeder/yaml-cpp repository.

## Why yaml-cpp Does Not Preserve Comments Automatically

Understanding the parser's behavior is essential before attempting to emit comments. The scanner recognizes comment tokens, but they never enter the node tree.

### Comment Detection During Scanning

In [`src/scanner.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/scanner.cpp), the `Scanner::ScanToNextToken` method (lines 190-205) detects comments starting with `#` and skips them until a line break. The regular expression used for this pattern is defined in [`src/exp.h`](https://github.com/jbeder/yaml-cpp/blob/main/src/exp.h) as `Exp::Comment()` (line 124). However, this token is discarded rather than stored.

### The Node Tree Limitation

Because yaml-cpp's `Node` class represents only data values (scalars, sequences, and maps), there is no attachment point for comment metadata. This design choice keeps the API simple and memory-efficient, but it means **you cannot retrieve comments from a parsed document**.

## How to Emit YAML Comments in yaml-cpp

To emit comments, you use the `Emitter` class with the `YAML::Comment` helper. This creates an internal `_Comment` object that the emitter knows how to format.

### The Emitter API for Comments

The core emission logic resides in three locations:

- **[`src/emitter.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/emitter.cpp)** (lines 49-60): The `Emitter::Write(const _Comment&)` overload receives the comment object and forwards it to the output routine.
- **[`src/emitterutils.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/emitterutils.cpp)** (lines 58-75): The `Utils::WriteComment` function handles the actual formatting, including line break splitting and indentation.
- **[`src/emitterstate.h`](https://github.com/jbeder/yaml-cpp/blob/main/src/emitterstate.h)** (lines 106-109): Stores the `preCommentIndent` and `postCommentIndent` values that control spacing.

### Basic Comment Emission Example

Here is how to emit a simple comment before a map:

```cpp
YAML::Emitter out;
out.SetPreCommentIndent(2);   // spaces before '#'
out.SetPostCommentIndent(1);   // spaces after '#'

out << YAML::Comment("This is a comment");
out << YAML::BeginMap
    << YAML::Key << "name" << YAML::Value << "Alice"
    << YAML::EndMap;

std::cout << out.c_str();

```

Output:

```

  # This is a comment

{
  name: Alice
}

```

### Controlling Comment Indentation

The `Emitter` class exposes two methods to control comment appearance:

- **`SetPreCommentIndent(n)`**: Sets how many spaces appear before the `#` character.
- **`SetPostCommentIndent(n)`**: Sets how many spaces appear between the `#` and the comment text.

These values are stored in the `EmitterState` object and consulted by `Utils::WriteComment` when formatting output.

## Advanced Comment Emission Patterns

Multi-line comments and programmatic document construction require specific handling to maintain proper formatting.

### Multi-Line Comments

When you pass a string containing newlines to `YAML::Comment`, the emitter splits it and prefixes each line with the comment marker. The `Utils::WriteComment` implementation in [`src/emitterutils.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/emitterutils.cpp) handles this automatically:

```cpp
YAML::Emitter out;
out.SetPreCommentIndent(4);   // four spaces before '#'
out.SetPostCommentIndent(0);  // no space after '#'

out << YAML::Comment("First line\nSecond line\nThird line")
    << YAML::BeginSeq
    << "item1" << "item2"
    << YAML::EndSeq;

```

Output:

```

    #First line
    #Second line
    #Third line
[
  item1,
  item2
]

```

### Comments in Programmatic Document Construction

You can interleave comments when building documents from existing `Node` objects:

```cpp
YAML::Node root;
root["version"] = "1.0";

YAML::Emitter out;
out << YAML::Comment("Generated by my tool")
    << YAML::BeginMap
    << YAML::Key << "settings" << YAML::Value << root
    << YAML::EndMap;

std::cout << out.c_str();

```

Output:

```

# Generated by my tool

{
  settings:
    version: 1.0
}

```

## Summary

Key points for preserving and emitting YAML comments in yaml-cpp:

- **yaml-cpp discards comments during parsing**—they are recognized by the scanner in [`src/scanner.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/scanner.cpp) but never stored in the node tree.
- **Use `YAML::Comment` with an `Emitter`** to emit comments explicitly; this creates an internal `_Comment` object processed by `Emitter::Write` in [`src/emitter.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/emitter.cpp).
- **Control indentation** with `SetPreCommentIndent` and `SetPostCommentIndent` to match your formatting requirements.
- **Multi-line comments** are automatically split and re-indented by the `Utils::WriteComment` function in [`src/emitterutils.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/emitterutils.cpp).
- **Comments cannot be retrieved from parsed documents**—if you need to preserve comments from input, you must capture them separately before parsing.

## Frequently Asked Questions

### Can yaml-cpp preserve comments when loading a file?

No. The scanner in [`src/scanner.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/scanner.cpp) detects and skips comments during tokenization, but they are not attached to the resulting `Node` objects. If you need to preserve comments from an existing file, you must implement a custom scanner or preprocess the file to capture comment positions separately.

### How do I add comments to specific nodes in a YAML document?

Since comments are not node properties, you must emit them at the correct position in the output stream using `YAML::Comment` before the relevant content. The emitter processes comments in the order they are written, so place `out << YAML::Comment("...")` immediately before the key, value, or sequence element you want to annotate.

### What is the difference between pre-comment and post-comment indentation?

Pre-comment indentation (`SetPreCommentIndent`) controls how many spaces appear before the `#` character, typically used to align comments with surrounding content. Post-comment indentation (`SetPostCommentIndent`) controls the space between the `#` and the comment text, commonly set to 1 for readability or 0 for compact output. These values are stored in `EmitterState` and applied by `Utils::WriteComment` in [`src/emitterutils.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/emitterutils.cpp).

### Can I emit comments at the end of a line (inline comments)?

The yaml-cpp emitter API does not directly support inline end-of-line comments. The `YAML::Comment` helper emits comments on their own lines. To achieve inline comments, you would need to manipulate the raw output stream or use a different library, as the current implementation in [`src/emitter.cpp`](https://github.com/jbeder/yaml-cpp/blob/main/src/emitter.cpp) always places comments on new lines.