@romanpauk/dingo
ADependency Injection Container for C++, with DI, next-gen and an 'o' in a name.
Install
agr install @romanpauk/dingo --target codexWrites 1 file into AGENTS.md, pinned to git-4a2df34d.
- AGENTS.md
Document
Quality Gate
Before finishing a non-trivial change, run the repository quality gate:
cmake --build build -t check
This target verifies C++ formatting and Markdown formatting. On non-Windows
builds it also runs clang-tidy through check-tidy; Windows skips clang-tidy.
Do not wire it into the default build; it is an explicit validation target for
agents, local review, and CI.
Run clang-tidy directly when you want only static-analysis coverage:
cmake --build build -t check-tidy
This target requires DINGO_EXAMPLES_ENABLED=ON so clang-tidy can analyze real
example translation units for this header-only library.
C++ formatting is pinned to clang-format 21 from the locked uv
development environment. If the local system formatter differs, configure CMake
with the locked executable:
cmake -S . -B build -DDINGO_DEVELOPMENT_MODE=ON \
-DDINGO_CLANG_FORMAT_EXE="$(uv run --locked python -c 'import shutil; print(shutil.which("clang-format"))')"
For any C++ source or header edit, format before verification:
cmake --build build -t format
cmake --build build -t check-format
If the build directory has not been configured, configure a development build
first:
cmake -S . -B build -DDINGO_DEVELOPMENT_MODE=ON
If the quality gate fails because of files unrelated to the current change, do not ignore the failure. Either fix the stale formatting as part of the change or call out the blocker explicitly in the final update.
Repository README
Describes romanpauk/dingo as a whole, which may contain artifacts other than this one. Where this artifact had no useful description of its own, its summary was taken from here.
Dingo
Dependency Injection Container for C++, with DI, next-gen and an 'o' in a name.
Dingo builds object graphs from ordinary C++ types with runtime or compile-time registration. Scopes and storage policies control ownership explicitly, and user types stay free of framework macros or base classes.
Resolution applies supported ownership and interface conversions automatically, so one registration can satisfy references, pointers, smart pointers, and interface lookups when the selected storage and scope allow it.
Tested with:
- C++17, C++20, C++23, C++26
- GCC 13-15
- Clang 18-20
- Visual Studio 2022, 2026
Runtime Registration
Runtime registration uses container<> with registrations added through
register_type<...>(), which fits graphs assembled by ordinary control flow.
Example code included from examples/container/quick_runtime.cpp:
// User types do not need Dingo-specific base classes or macros.
struct A {
A() = default;
};
struct B {
B(A &, std::shared_ptr<A>) {}
};
struct C {
C(B *, std::unique_ptr<B> &, A &) {}
};
container<> container;
// A and B are shared, so every resolution reuses the same instances.
container.register_type<scope<shared>, storage<std::shared_ptr<A>>>();
container.register_type<scope<shared>, storage<std::unique_ptr<B>>>();
// C is unique, so every resolve<C>() creates a fresh C.
container.register_type<scope<unique>, storage<C>>();
// Constructor arguments are resolved recursively, including ownership
// conversions from the registered storage forms.
C c = container.resolve<C>();
struct D {
A &a;
B *b;
};
// Construct an unmanaged object using dependencies from the container.
D d = container.construct<D>();
// Or invoke a callable with resolved arguments.
D e = container.invoke([&](A &a, B *b) { return D{a, b}; });
Compile-Time Registration
Compile-time registration uses bindings<...> with container<bindings<...>>
or static_container<bindings<...>>, which fits graphs known in the type
system.
Example code included from examples/container/quick_static.cpp:
struct A {
A() = default;
};
struct B {
B(A &, std::shared_ptr<A>) {}
};
struct C {
C(B *, std::unique_ptr<B> &, A &) {}
};
// Compile-time bindings declare the same storage and scope as runtime
// registration.
using app_bindings =
bindings<dingo::bind<scope<shared>, storage<std::shared_ptr<A>>>,
dingo::bind<scope<shared>, storage<std::unique_ptr<B>>>,
dingo::bind<scope<unique>, storage<C>>>;
container<app_bindings> container;
// Resolution still uses the same API.
C c = container.resolve<C>();
struct D {
A &a;
B *b;
};
// construct() and invoke() work with compile-time registration, too.
D d = container.construct<D>();
D e = container.invoke([&](A &a, B *b) { return D{a, b}; });
Installation
For CMake-based projects, FetchContent is the documented integration path. The
project exports the dingo::dingo interface target and has no runtime
dependencies.
Example code included from test/fetchcontent/CMakeLists.txt:
include(FetchContent)
FetchContent_Declare(dingo
GIT_REPOSITORY https://github.com/romanpauk/dingo.git
GIT_TAG v0.2.0)
FetchContent_MakeAvailable(dingo)
target_link_libraries(dingo_fetchcontent_test PRIVATE dingo::dingo)
When working from a checkout, the top-level CMake project also supports
add_subdirectory(...).
Documentation
- Getting Started: installation, runtime
registration, compile-time registration,
resolve(),construct(), andinvoke(). - Core Concepts: registration modes, scopes, storage, arrays, variants, factories, interfaces, and multibindings.
- Advanced Topics: indexed resolution, annotations, runtime and compile-time registration modes, nesting, RTTI, allocation, and runtime notes.
- Architecture: registration flow, lookup shape, extension traits, and conversion rules.
- Examples: a guided index of runnable examples in
examples/. - Development: local development builds, repo tooling, Markdown verification, and CI container notes.
- Motivation and History: background on how the library evolved.
Feature Summary
- Non-intrusive registration of ordinary C++ types
- Runtime and compile-time registration modes
- Explicit control over lifetime and stored representation
- Constructor deduction with explicit factory overrides when needed
- Interface bindings and multibindings
- Indexed and annotated resolution
- Parent-child container nesting
- Array support for raw arrays and smart-pointer-backed arrays
- Explicit variant construction plus whole-variant or held-alternative resolution
- Custom RTTI and allocator hooks
- Extensive generated matrix tests across features, registration modes, scopes, stored types, resolved types, and containers. See the generated matrix test model.
Related Projects
For DI library comparisons, also take a look at:
Trustgrade A
- passBody integrity
Whether the stored document is plausibly the kind of file the artifact declares, rather than something fetched by mistake.
- passType matchnot applicable to this artifact type
Whether the artifact is really the kind of thing its metadata claims it is.
- passFreshness
How long since the source repository was last pushed to.
- passPrompt injection
Scans the artifact's own text for instructions aimed at your agent rather than at you.
- passLicense
Whether the source repository declares an SPDX license permissive enough to redistribute.
How the grade is calculated
Each check contributes 0 points when it passes, 1 when it warns, and 2 when it fails. The total maps to a letter:
- Aevery check passed
- Bone warning
- Ctwo warnings
- Dprompt injection or body integrity failed, or three warnings
- Fone of those failed, and something else is wrong
These are automated hygiene checks, not a security audit, and not a dependency or vulnerability scan. A grade of A means nothing was flagged — not that the artifact is safe.
Versions
git-4a2df34dcd2d2026-08-06