boost-ext / di

C++14 Dependency Injection Library
https://boost-ext.github.io/di
1.13k stars 136 forks source link

enforce deduction of const std::shared_ptr<T> & #557

Open SteRoh opened 7 months ago

SteRoh commented 7 months ago

Context

In my case i want to share a logger instance through my classes therefore I pass some const std::shared_ptr<T>& into my classes.

Actually i cant change my constructor arguments, because i have to check if boost::di can be used non-invasive. Is there a way to enforce the right deduction of const std::shared_ptr<T>& ? Or how to handle this case?

auto log = std::make_shared<logger>();

  auto injector = di::make_injector(
      di::bind<logger>().to(log),  
      di::bind<MyType>,     // needs a const std::shared_ptr<logger>&     
      di::bind<ANestedType> // needs a const std::shared_ptr<logger>&     
  );

Expected Behavior

Each instance of my class is using the same logger.

Logoutput # 0 msg: MyType created
Logoutput # 1 msg: ANestedType created
Logoutput # 2 msg: log from ANestedType
Logoutput # 3 msg: log from MyType

Actual Behavior

The Logger which shall be passed by const std::shared_ptr<T>& is somehow dangling. In my example, it is obv not the same logger instance. Even the address sanitizer is complaining.

Logoutput # 0 msg: MyType created
Logoutput # 1843005592 msg: ANestedType created
Logoutput # 1843005593 msg: log from ANestedType
Logoutput # 1 msg: log from MyType

Steps to Reproduce the Problem

  1. https://godbolt.org/z/ezW4d56Ea
  2. remove the reference of the signature const std::shared_ptr<logger>& log

Specifications

krzysztof-jusiak commented 7 months ago

Note sure why scoped instance would not participate in the scope deduction for nested types but that seems the case. It might be easier to create a logger with di as well. That seems to work but not sure whether it fits your use case? https://godbolt.org/z/ejrT6hqK3

SteRoh commented 7 months ago

Thx for the impressing fast response @krzysztof-jusiak :)

I stripped down the Problem to this simple example but my actual use case looks like this:

  1. LoggerFactory will be created once with some config files
  2. LoggerFactory is the only one who can create std::shared_ptr<logger>
  3. MyClass( const std::shared_ptr& logger)
  4. OtherClass( const std::shared_ptr& logger)

So within the injector i need one LoggerFactory and i thought i have to bind the const std::shared_ptr<logger>& to the create() Function of the LoggerFactory.

https://godbolt.org/z/YTbbo15rY I have no idea what to do inside the injector :)

Maybe there is an easy solution, but i could not find any examples which show this factory Use case.