kangaru: a header-only dependency injection container for C++
🦘 A dependency injection container for C++11, C++14 and later
At a glance
- What is it?
- kangaru is an inversion of control container for C++11 and later, header-only because of its heavy template use, with an explicit service configuration API and a newer autowire API that derives the wiring from friend functions. It is MIT licensed and requires no changes to the classes it constructs.
- Who is it for?
- kangaru suits a C++ project that has grown a web of constructor dependencies and wants them wired by a container without inheriting a framework, since it is header-only, non-intrusive and leaves your classes untouched. It is the wrong tool if you need runtime configuration of the graph or thread-safe dynamic scoping, neither of which the library claims, and it is the wrong tool if you cannot accept a template-heavy dependency in your include path.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What problem it solves in a C++ codebase
kangaru is an inversion of control container for C++11, C++14 and later. The README describes it as providing many features to automate dependency injection and reducing the amount of wiring boilerplate in your code, achieved by exposing in-code configuration for autowiring, constructor injection and function parameter injection. Two design commitments are stated up front. It aims to keep the simplest interface possible and boilerplate to a minimum, and it does not want to be intrusive into user or library code.
That second point is the one that matters most for C++ specifically. Most IoC containers in other languages either require attributes on your classes, a registration file, or a base class. The feature list says it plainly: non intrusive, no existing classes need modification. You tell the container how to construct your types, store and inject them.
The audience is a C++ developer with a growing dependency graph and no appetite for a framework. The library is header-only because of its extensive use of templates, which means adding it is a matter of include paths rather than a build dependency, and it is MIT licensed with a vcpkg package and CMake export for installation.
The name has a double meaning the README explains: kangaru comes from the container's feature to inject itself into a service as a dependency, and because kangaroos are awesome.
The explicit service configuration
The traditional API describes the dependency graph in code, as service type definitions that inherit from kgr::service or kgr::single_service. Here is the whole shape of it:
#include <kangaru/kangaru.hpp>
#include <cassert>
// We define some normal classes with dependencies between them
struct Camera {};
struct Scene {
Camera& camera;
};
// The following is the configuration of our user classes above.
// The structure and dependency graph is defined by these configs.
// Camera is a single service so the service has a shared instance.
// It will be injected and returned as a reference.
struct CameraService : kgr::single_service<Camera> {};
// Scene is not single, so the container returns scenes by value.
// Also, we depend on a camera to be constructed.
struct SceneService : kgr::service<Scene, kgr::dependency<CameraService>> {};
int main()
{
kgr::container container;
// The service function returns instances of the normal classes.
Scene scene = container.service<SceneService>();
Camera& camera = container.service<CameraService>();
assert(&scene.camera == &camera); // passes, both cameras are the same instance.
}Two type traits carry the semantics. single_service means the container holds one shared instance, which is why Camera comes back as a reference and the assert holds: both lookups return the same object. Plain service means a new instance per request, returned by value. And kgr::dependency<CameraService> is how the graph edge is declared, so SceneService cannot be constructed without a CameraService.
The important detail is that Camera and Scene are ordinary classes. They are not modified, not derived from anything, and carry no macros. The configuration lives entirely in the service types.
The autowire API and the friend function trick
Newer versions of kangaru support an autowire API, and the README shows the same example rewritten. The user classes now declare a friend function that maps a type to a service tag:
#include <kangaru/kangaru.hpp>
#include <cassert>
// We define some normal classes with dependencies between them
// And we added the autowire configuration
struct Camera {
// friend functions are faster to lookup than plain free functions
friend auto service_map(Camera const&) -> kgr::autowire_single;
};
struct Scene {
Camera& camera;
friend auto service_map(Scene const&) -> kgr::autowire;
};
// No need for service definitions
int main()
{
kgr::container container;
// We invoke a lambda that receives injected parameters.
// The container will figure how to wire the classes using
// either the constructor parameters or aggregate initialization
container.invoke([](Scene scene, Camera& camera) {
assert(&scene.camera == &camera); // passes, both cameras are the same instance.
});
}The mechanism is a hidden friend whose argument type is the type being mapped, found by argument-dependent lookup rather than by a registry. The comment explains the design choice: friend functions are faster to lookup than plain free functions. Returning kgr::autowire_single marks the type as a shared service and kgr::autowire marks it as a per-request one, which reproduces the single_service and service distinction without a separate service type.
The container.invoke call then takes a lambda whose parameters are the services you want, and the container works out the wiring from either the constructor parameters or aggregate initialisation. Function parameter injection is a first-class feature rather than an afterthought, which is unusual for a C++ container and is what makes the lambda form possible.
Installing with CMake or vcpkg
Building from source is a clone, a CMake preset and an optional install:
$ git clone https://github.com/gracicot/kangaru.git && cd kangaru$ cmake --preset export # -DKANGARU_HASH_TYPE_ID=OFF # uncomment for older compiler supportThe preset generates the project and exports the package information. The comment on the same line is worth noticing: a KANGARU_HASH_TYPE_ID option can be turned off for older compiler support, which tells you the library uses a compiler feature that the oldest supported compilers lack.
Installing to the system is the optional second step:
$ sudo cmake --build --preset export --target install # optional stepFor Windows, vcpkg is the route. Install vcpkg, then install the package for the default architecture:
vcpkg install kangaruor for a specific target such as 64-bit Windows:
vcpkg install kangaru:x64-windowsThe repository carries a vcpkg.json manifest alongside a CMakeLists.txt and CMakePresets.json, and a cmake/ directory for the export logic.
Consuming it from another project needs find_package and a link to the imported target:
find_package(kangaru 4.3 REQUIRED)target_link_libraries(<YOUR TARGET> PUBLIC kangaru::kangaru)after which the include is:
#include <kangaru/kangaru.hpp>If you skipped the install step, you can point CMake at the build directory instead:
# in your project build directory
$ cmake .. -DCMAKE_PREFIX_PATH=../../path/to/kangaru/buildCompiler requirements and the size of the template cost
Kangaru is tested by continuous integration with all major compiler versions, and the README gives the minimums: MSVC 2015 update 3 or better, GCC 4.8.5 or better, Clang 3.6 or better, and AppleClang 7.0 or better. Those are old floors, which is good for adoption and means the library is not requiring a recent toolchain.
The cost of a header-only template library is compile time and binary size, and the README is not silent about the trade-offs. The feature list claims low runtime overhead and clean diagnostics at compile-time, and the What's Next section lists tests for compile-time errors and better messages for compile-time errors as ongoing work, along with even better performance and exposing a zero-overhead interface for cases it can apply.
That last item is the honest signal. A zero-overhead interface, meaning a way to get the resolved dependencies without paying for the container machinery at all, is on the wishlist rather than shipped, so today the container is always in the path. For a service that is constructed once and used in a hot loop, that cost is amortised. For a container consulted per request in a tight loop, it is not.
The repository layout backs up the picture of a serious library: there is a benchmark/ directory at the top level, a test/ directory, a doc/ directory for the documentation and tutorial, an examples/ directory with around a dozen example projects including an abstract_factory example, and CMakePresets.json for the build configuration.
What is still on the wishlist
The What's Next section is short and reads like an honest gap list rather than a roadmap. There are tests for compile-time errors, so that misuse of the API produces a compile failure rather than a confusing diagnostic. There are better messages for compile-time errors, marked ongoing. There are service sources, with a link to issue 41 for detail. There is even better performance, also marked ongoing. And there is the plan to expose a zero-overhead interface for cases it can apply.
Service sources are the least self-explanatory item and the most structurally interesting. A service source would be a way to provide instances from outside the container, which is how you would integrate a container with a codebase that already has its own object lifetimes, or with a third-party library whose objects you do not own. Until that exists, the container is the sole source of the services it resolves, which narrows how far the library can be introduced into an existing codebase gradually.
The documentation lives in the wiki and in the doc folder, and the README links a wandbox permalink so the example can be run in a browser without a local toolchain, which is the fastest way to see whether the library suits you before committing to it.
Where kangaru is the wrong choice
Three limits are worth naming. The first is that the graph is fixed at compile time. Services are expressed as types and friend functions, which is what makes the container fast and non-intrusive, and it is also what means you cannot decide at runtime which implementation of an interface to use based on a configuration file. A container with runtime binding is a different design, and if that is what you need, kangaru is not it.
The second is template and header-only weight. Kangaru is header-only because of its extensive use of templates, so every translation unit that includes it pays the compile-time cost, and there is no way to take a binary dependency instead. In a large project with many translation units this shows up in build times. The project does not claim the library is free at runtime and free to compile; the zero-overhead interface is still a wishlist item.
The third is the release cadence against the commit activity. The tagged releases are v4.3.2 from 2024-04-29, v4.2.6 from 2024-04-29 and v4.3.1 from 2022-08-15, while the last push to the repository was on 2026-10-19, so the tree is being worked on well after the last version tag. For a header-only library that is less disruptive than for a binary dependency, since you can build from a commit, but it does mean the version you pin from a package manager may be older than the code you would get from master.
The licence is MIT, which is permissive, with the main requirement of keeping the copyright notice in distributions. The repository also carries a SECURITY.md, a CONTRIBUTING.md and a CODE_OF_CONDUCT.md, and the CII Best Practices badge indicates the project is registered with the Core Infrastructure Initiative, which is a sign of the maintainer's intent to keep the project in good standing rather than treat it as a side project.
Editorial conclusion
kangaru suits a C++ project that has grown a web of constructor dependencies and wants them wired by a container without inheriting a framework, since it is header-only, non-intrusive and leaves your classes untouched. It is the wrong tool if you need runtime configuration of the graph or thread-safe dynamic scoping, neither of which the library claims, and it is the wrong tool if you cannot accept a template-heavy dependency in your include path. Verify first that your compiler meets the stated minimums, MSVC 2015 update 3, GCC 4.8.5, Clang 3.6 or AppleClang 7.0, and note that the newest tagged release is v4.3.2 from 2024-04-29 while the last push to the repository was on 2026-10-19.
Frequently asked questions
What is kangaru and what does it do?
It is an inversion of control container for C++11, C++14 and later that automates dependency injection and reduces wiring boilerplate. You tell the container how to construct, store and inject your types, and no existing class needs to be modified.
How do I install kangaru?
Clone the repository and run cmake --preset export, optionally followed by sudo cmake --build --preset export --target install. On Windows, install vcpkg and run vcpkg install kangaru. Then in your project use find_package(kangaru 4.3 REQUIRED) and link to kangaru::kangaru.
What is the difference between kgr::service and kgr::single_service?
A single_service type has a shared instance held by the container and is returned as a reference, while a plain service produces a new instance per request and is returned by value. Dependencies between them are declared with kgr::dependency.
How does the autowire API in kangaru work?
You declare a hidden friend function on your type, for example friend auto service_map(Camera const&) -> kgr::autowire_single, and the container finds it by argument-dependent lookup. The comment in the README notes that friend functions are faster to lookup than plain free functions, and the container then wires the classes using either constructor parameters or aggregate initialisation.
Which compilers does kangaru support?
The minimum required versions are MSVC 2015 update 3 or better, GCC 4.8.5 or better, Clang 3.6 or better and AppleClang 7.0 or better, tested by continuous integration with all major compiler versions.
Is kangaru header-only?
Yes. The README states it is a header only library because of its extensive use of templates, so there is no binary to link and no runtime dependency to deploy.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/gracicot-kangaru)Was this useful?