Sounds like you have a big project planned!
You need rock solid tools when undertaking a big project. I was up late one night last week and almost convinced myself that boost::dynamic_bitset was broken. Well this is unlikely, the boost libraries are well regarded and used by thousands, so I just have to dig in and find
my error. This is bad (there is some error in my program I don't understand at the moment) but also good (it is within my power to fix it). If the tools you are using are not rock solid you do not have this certainty.
Structurally, dependency injection is the same as the '
bridge pattern' (multiplied up). I do not use the factory pattern, just make a dependent object and pass it into the object that needs it in the constructor. The object needing the dependency stores a reference to the required object. For example, I am doing a graphical project where the output device could be anything. It could be a real time animation or a set of raytracer scene description files, one per scene. In the future it may be 3D animated output. So I have an abstract OutputDevice class which models this output and various concrete derived classes. To draw the scene a Render class needs an OutputDevice which it just receives as an argument in its constructor. The Renderer does not know if it is writing to the screen, a file or some 3D hardware, it just uses OutputDevice's standardised interface.
This does mean that I have some fairly lengthy constructor argument lists. I am hoping to alleviate that problem using the named parameter idiom.
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.20
So 'dependency injection' is really just a type of object composition, which is why I am not sure why your requirements are so intense. Is object composition the right way of combining the units you are chaining? Maybe they should communicate in some other way?
As regards manual dependency injection I've done a bit of googling and there are plenty of opinion pieces for and against this that or the other method of injection. There are two ways of manually injecting: "constructor injection" and "setter injection". In setter injection you provide public member functions that allow you to set the various dependencies an object may need.
In C++ you also need to decide whether to use a reference or pointer inside the class to point to the dependency. If you use a reference then you have to use constructor injection and the dependency is fixed throughout the object's lifetime. With a pointer you can use setter injection and also change the dependency.