Mr.Docs

Mr.Docs is a C++ reference documentation generator built on Clang/LLVM. It reads your project’s source through a compilation database, builds a complete symbol corpus from the real Clang AST, and emits documentation in several formats. The same corpus feeds rendered documents intended for human readers and structured data intended for downstream tools.

graph LR CPP["C++ source
doc comments"]:::input CFG[Configuration]:::input CORPUS([Symbol corpus]):::stage GENS([Generators]):::stage RENDERED[Rendered documentation]:::output DATA[Structured data]:::output EXT[Extensions]:::ext CPP --> CORPUS CFG --> CORPUS CORPUS --> GENS GENS --> RENDERED GENS --> DATA EXT <-.-> CORPUS EXT <-.-> GENS

What Mr.Docs reads

Real C++ through Clang. Namespaces, classes and structs, function and class templates, concepts, deduction guides, enumerations, type aliases, variables, and using declarations all come through; partial and explicit specializations come along because the parser has resolved them already.

Doc comments in the Javadoc and Doxygen tradition. Block-level commands describe parameters, return values, exceptions, preconditions, and the surrounding prose. Inline commands handle emphasis, code spans, links, math, and the small markup pieces between sentences. The Documenting the Code section spells out which comments Mr.Docs understands and how each one renders.

A function-object template
struct sqrt_fn
{
    /** Compute the integer square root.

        Returns \f$\lfloor\sqrt{value}\rfloor\f$, the largest integer whose
        square does not exceed `value`, computed via bit manipulation.

        @par Complexity
        Logarithmic in `value`, about $O(\log value)$ iterations.

        @note Returns zero for zero input.

        @tparam T An integral type.
        @param value The integral value, which must be non-negative.
        @pre `value >= 0`.
        @return The integer square root of `value`.
    */
    template <typename T>
    [[nodiscard]] constexpr
    std::enable_if_t<std::is_integral_v<T>, T>
    operator()(T value) const noexcept;
};

constexpr sqrt_fn sqrt = {};

Doc comments carry LaTeX math too. The \f$…​\f$ and $…​$ spans in the comment above render as real symbols, so a complexity like \(O(\log n)\) or a definition like \(\lfloor\sqrt{value}\rfloor\) reads the way it would in a paper.

What Mr.Docs produces

  • Several generators emit documentation in formats ranging from rendered documents for human readers to structured data for downstream tooling.

  • Customizable templates for the rendering generators, so the visual layout and the content shape of the output can be changed without touching the binary.

  • An extension surface that lets users plug in custom generators, register helpers used by the templates, and transform the corpus before it reaches a generator.

The Configuration Options section covers how to select a generator and shape its output. The Generators section covers how templates are organized and how to override or replace them.

PreviewยทThe same declaration, rendered
sqrt

Compute the integer square root.

Synopsis

Declared in <sqrt.cpp>

template<typename T>
[[nodiscard]]
constexpr
T
sqrt(T value) noexcept
requires std::is_integral_v<T>;

This function is defined as an Algorithm Function Object (AFO).

Description

Returns \(\lfloor\sqrt{value}\rfloor\), the largest integer whose square does not exceed value, computed via bit manipulation.

Complexity

Logarithmic in value, about \(O(\log value)\) iterations.

Returns zero for zero input.

Return Value

The integer square root of value.

The return value should not be discarded.

Template Parameters

Name

Description

T

An integral type.

Parameters

Name

Description

value

The integral value, which must be non‐negative.

Preconditions
  • value >= 0.

What Mr.Docs makes of the declaration above.

Why generate from source

C++ API design is hard, and the moment you write a function signature is usually the moment you know the most about what it is supposed to do. Wait a week, and the details start to fade. Wait a month, and you reconstruct them from the call sites. Writing the documentation now, next to the declaration, captures what you already have in your head.

Keeping the docs next to the code does two things at once:

  • It makes them easier to update when a signature changes (you see them in the same diff), and

  • It makes them more likely to be written in the first place (no separate file to open).

It also pays off before any site is generated. Editors show the same /** …​ */ comment on hover and in signature help, and AI coding assistants read it as context while editing the same file. One comment written next to the declaration serves the reader of the reference, the developer at the call site, and the assistant working alongside them.

Handwritten reference documentation works for small libraries. It stops scaling as soon as the codebase outgrows what one developer can hold in memory, and it drifts the moment a signature changes without an edit to the matching prose.

Generating the reference from the headers fixes the drift, but only if the generator reads those headers as the compiler does. Other tools often cannot do that, and the workaround is to keep a parallel ill-formed declaration just for the documentation tool. That defeats the point: the source code no longer reflects what is compiled. The Migration Notes walk through the C++ idioms where this happens.

Mr.Docs Other Tools Manual No Reference

Reader-friendly output

Yes

Yes

Yes

No

Stays in sync with source

Yes

Yes

No

No

IDE friendly

Yes

Yes

No

No

AI friendly

Yes

Yes

No

No

No source-code workarounds

Yes

No

Yes

No

Low author overhead

Yes

No

No

Yes

Single source of truth

Yes

No

No

No

Mr.Docs gives readers a presentable reference without extra work for developers, so the documented C code remains the compiled C code.

See it in action

The Demo Gallery hosts Mr.Docs-generated reference documentation for several third-party libraries in every supported output format.