boost-ext / di

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

Compile error binding an instance with runtime injector #458

Open 0ctopus13prime opened 4 years ago

0ctopus13prime commented 4 years ago

Expected Behavior

It's working when make an plain injector with an instance binding, but it becomes strangely not working as soon as the type is changed to runtime_injector

I referred runtime_provider_example and made it run by my self without any compile errors.

Why

di::extension::runtime_injector rt_module() { return di::make_injector(di::bind<i4>().to<impl4>()); }

this work in the example, but not in mine?

Thank you in advance

Actual Behavior

My dev environment described at the bottom. Please see Specifications section

GCC8 error

I didn't attach all GCC compile error logs which have quite long lines than Clang on purpose But few lines seem to be worth to consider

/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/alloc_traits.h:159:68: error: no type named ‘value_type’ in ‘struct boost::di::v1_1_0::core::any_type<std::_Sp_counted_deleter<std::nullptr_t, boost::di::v1_1_0::core::any_type<std::shared_ptr<A>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> >, boost::di::v1_1_0::core::any_type<std::shared_ptr<A>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> >, (__gnu_cxx::_Lock_policy)2>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> >’
       using difference_type = typename _Diff<_Alloc, pointer>::type;

/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/alloc_traits.h:88:43: error: no type named ‘value_type’ in ‘struct boost::di::v1_1_0::core::any_type<std::_Sp_counted_deleter<std::nullptr_t, boost::di::v1_1_0::core::any_type<std::shared_ptr<A>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> >, boost::di::v1_1_0::core::any_type<std::shared_ptr<A>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> >, (__gnu_cxx::_Lock_policy)2>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> >’
       typedef typename _Alloc::value_type value_type;

/home/kdy/practice/boost-di-explore/deps/boostdi/src/include/boost/di/extension/providers/runtime_provider.hpp:125:37: error: call of overloaded ‘make(const boost::di::v1_1_0::core::dependency<boost::di::v1_1_0::scopes::instance, A, std::shared_ptr<A>, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>&)’ is ambiguous
       return make<typename T::given>(binding);

/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/allocated_ptr.h:97:60: error: ‘allocate’ is not a member of ‘std::allocator_traits<boost::di::v1_1_0::core::any_type<std::_Sp_counted_deleter<std::nullptr_t, boost::di::v1_1_0::core::any_type<std::shared_ptr<A>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> >, boost::di::v1_1_0::core::any_type<std::shared_ptr<A>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> >, (__gnu_cxx::_Lock_policy)2>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> > >’
       return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) };
                     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
/opt/rh/devtoolset-8/root/usr/include/c++/8/bits/allocated_ptr.h:97:69: error: could not convert ‘{__a, <expression error>}’ from ‘<brace-enclosed initializer list>’ to ‘std::__allocated_ptr<boost::di::v1_1_0::core::any_type<std::_Sp_counted_deleter<std::nullptr_t, boost::di::v1_1_0::core::any_type<std::shared_ptr<A>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> >, boost::di::v1_1_0::core::any_type<std::shared_ptr<A>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> >, (__gnu_cxx::_Lock_policy)2>, boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>, boost::di::v1_1_0::aux::integral_constant<bool, false> > >’
       return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) };

Clang7 error

In file included from /home/kdy/practice/boost-di-explore/src/main.cpp:1:
/home/kdy/practice/boost-di-explore/deps/boostdi/src/include/boost/di/extension/providers/runtime_provider.hpp:125:14: error: call to member function 'make' is ambiguous
      return make<typename T::given>(binding);
             ^~~~~~~~~~~~~~~~~~~~~~~
/home/kdy/practice/boost-di-explore/src/main.cpp:12:12: note: in instantiation of function template specialization 'boost::di::v1_1_0::extension::detail::injector<boost::di::v1_1_0::extension::assert_error_policy, boost::di::v1_1_0::extension::shared_config>::install<boost::di::v1_1_0::core::dependency<boost::di::v1_1_0::scopes::instance, A, std::shared_ptr<A>, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>, 0>' requested here
  injector.install(di::bind<A>().to(a));
           ^
/home/kdy/practice/boost-di-explore/deps/boostdi/src/include/boost/di/extension/providers/runtime_provider.hpp:158:8: note: candidate function [with T = std::shared_ptr<A>, TBinding = boost::di::v1_1_0::core::dependency<boost::di::v1_1_0::scopes::instance, A, std::shared_ptr<A>, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>]
  auto make(const TBinding &) -> decltype(make_impl<T>(typename ctor_traits<T>::type{})) {
       ^
/home/kdy/practice/boost-di-explore/deps/boostdi/src/include/boost/di/extension/providers/runtime_provider.hpp:163:8: note: candidate function [with T = std::shared_ptr<A>, TBinding = boost::di::v1_1_0::core::dependency<boost::di::v1_1_0::scopes::instance, A, std::shared_ptr<A>, boost::di::v1_1_0::no_name, void, boost::di::v1_1_0::core::none>]
  auto make(const TBinding &binding) -> decltype(new T{binding.object_}) {
       ^
1 error generated.

Steps to Reproduce the Problem

#include <boost/di/extension/providers/runtime_provider.hpp>

class A {};

int main() {
  namespace di = boost::di;

  auto a = std::make_shared<A>();

  di::extension::runtime_injector injector =
          di::make_injector(di::bind<A>().to(a));

  // Or
  // di::extension::runtime_injector injector;
  // injector.install(di::bind<A>().to(a));

  return 0;
}

Specifications

0ctopus13prime commented 4 years ago

Context

The reason that I need this to be working is that sub instances need to use injector, and there seems no way to expose the actual type of the injector.

For example, In our app we assemble, integrate object tree in the first phase, and sub instances use the injector to do their job afterward.

In pseudo code it looks like this

auto injector = di::make_injector(
  .. bind this, that ...
);

// LoadSOPlugins : dlopen, dlsym etc.
for (auto p : LoadSOPlugins()) {
  p.Prepare(injector);
}

Now, the problem is that third party plugin can't expect what exact type of the injector will be. But I found that if injector type can be fixed with runtime_injector, then this problem can be resolved.

Therefore, any kind of working around, suggestions are welcome!

Thank you very much