Header-only dependency injection container for C++.
Dingo builds object graphs from ordinary C++ types. Scopes and storage policies control ownership explicitly, and user types stay free of framework macros or base classes.
Tested with:
- C++17, C++20, C++23, C++26
- GCC 12-14
- Clang 17-19
- Visual Studio 2019, 2022
Example code included from examples/container/quick.cpp:
// Class types to be managed by the container. Note that there is no special
// code required for a type to be used by the container and that conversions
// are applied automatically based on an registered type scope.
struct A {
A() {}
};
struct B {
B(A&, std::shared_ptr<A>) {}
};
struct C {
C(B*, std::unique_ptr<B>&, A&) {}
};
container<> container;
// Register struct A with a shared scope, stored as std::shared_ptr<A>
container.register_type<scope<shared>, storage<std::shared_ptr<A>>>();
// Register struct B with a shared scope, stored as std::unique_ptr<B>
container.register_type<scope<shared>, storage<std::unique_ptr<B>>>();
// Register struct C with an unique scope, stored as plain C
container.register_type<scope<unique>, storage<C>>();
// Resolving the struct C will recursively instantiate required dependencies
// (structs A and B) and inject the instances based on their scopes into C.
// As C is in unique scope, each resolve<C> will return new C instance.
// As A and B are in shared scope, each C will get the same instances
// injected.
/*C c =*/container.resolve<C>();
struct D {
A& a;
B* b;
};
// Construct an un-managed struct using dependencies from the container
/*D d =*/container.construct<D>();
// Invoke callable
/*D e =*/container.invoke([&](A& a, B* b) { return D{a, b}; });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 master)
FetchContent_MakeAvailable(dingo)
target_link_libraries(dingo_fetchcontent_test PRIVATE dingo::dingo)If you are working from a checkout, the top-level CMake project also supports
add_subdirectory(...).
- Getting Started: installation, first registrations,
resolve(),construct(), andinvoke(). - Core Concepts: scopes, storage, arrays, variants, factories, interfaces, and multibindings.
- Advanced Topics: indexed resolution, annotations, static vs dynamic containers, 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/. - Motivation and History: background on how the library evolved.
- Non-intrusive registration of ordinary C++ types
- Explicit control over lifetime and stored representation
- Array support for raw arrays and smart-pointer-backed arrays
- Explicit variant construction and variant storage resolution
- Constructor deduction with explicit factory overrides when needed
- Interface bindings and multibindings
- Indexed and annotated resolution
- Static and dynamic container configurations
- Parent-child container nesting
- Custom RTTI and allocator hooks
Development builds can enable tests, benchmarks, and runnable examples through
DINGO_DEVELOPMENT_MODE=ON. The library itself remains header-only.
If you are comparing DI libraries, also take a look at: