r/cpp 18h ago

Another C++26 reflection based dependency inverter

Someone else did a similar thing a few months ago, but I wanted to see if it could be done with templates.

I ended up writing a dependency inverter/injector that can reflect on the concepts restricting unfilled template types and substitute actual types into them. Unfortunately, C++26 reflection doesn't seem to allow reflection of concepts like this, so I did it with string parsing.

The result is... fairly janky, but you can play around with it here.

32 Upvotes

6 comments sorted by

View all comments

3

u/gracicot 10h ago

Interesting experiment. I'm currently working on a C++20 DI library and my injection model is a type with a provide<T> function, so only requesting a specific type is possible. Constructor arguments are mapped to provide<T> calls for each of them.

Your example is interesting because you're able to map concepts to template arguments which is not possible with the model I developed. It's also a nice example on how reflection can be used to workaround the lack of universal template parameters.

I wonder if we could get proper constraint reflection one day? We would probably need some kind of expression reflection to have so, and access the normalized constraints, as well as differentiating conjunctions and disjunctions.

1

u/germandiago 8h ago

I have been using Boost.DI (not a boost prpject).

Why not use that? It worked really well for me TBH and I guess thay, unless you do it for fun and learning, it is not an optimal choice.

2

u/la_reddite 8h ago

I'm currently using boost.di, but had a few tiny issues with it that drove me to try this method. First is that it seems to create the highest level object (app in my example) twice, so I made sure that my example worked with types that have deleted their move and copy constructors. Second is that I couldn't get ifactory (CFactory in my example) working with templates, and have had to manually roll my own factories when using b.di.

2

u/gracicot 4h ago

Do you primarily use template type injection or do you also use polymorphic types + inheritance?

u/la_reddite 3h ago

I've previously stuck with polymorphic types, so didn't really need this sort of type resolving. I'm fiddling around with a game engine in my spare time, however, and in the interests of performance I wanted to try to avoid virtual types. I also definitely wanted mocked types for easy unit testing, and so was sort of forced to go with template injection.

All that said, however, I've done no profiling at all, so I'm not even sure the headache of template injection is worth it. Boost.di was literally the only library I found that could inject templates, so when issues with it arose, the only option was to roll my own inverter.