// // Copyright (c) 2012-2020 Kris Jusiak (kris at jusiak dot net) // // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #pragma once #if (__cplusplus < 201305L && _MSC_VER < 1900) #error "[Boost::ext].DI requires C++14 support (Clang-3.4+, GCC-5.1+, MSVC-2015+)" #else #define BOOST_DI_VERSION 1'3'0 #define BOOST_DI_NAMESPACE_BEGIN \ namespace boost { \ inline namespace ext { \ namespace di { \ inline namespace v1_3_0 { #define BOOST_DI_NAMESPACE_END \ } \ } \ } \ } #if !defined(BOOST_DI_CFG_DIAGNOSTICS_LEVEL) #define BOOST_DI_CFG_DIAGNOSTICS_LEVEL 1 #endif #if defined(BOOST_DI_CFG_FWD) BOOST_DI_CFG_FWD #endif #define __BOOST_DI_COMPILER(arg, ...) __BOOST_DI_COMPILER_IMPL(arg, __VA_ARGS__) #define __BOOST_DI_COMPILER_IMPL(arg, ...) arg##__VA_ARGS__ #if defined(__clang__) #define __CLANG__ __BOOST_DI_COMPILER(__clang_major__, __clang_minor__) #define __BOOST_DI_UNUSED __attribute__((unused)) #define __BOOST_DI_DEPRECATED(...) [[deprecated(__VA_ARGS__)]] #define __BOOST_DI_TYPE_WKND(T) #define __BOOST_DI_ACCESS_WKND private #define __BOOST_DI_VARIABLE_TEMPLATE_INIT_WKND \ {} #elif defined(__GNUC__) #define __GCC__ #define __BOOST_DI_UNUSED __attribute__((unused)) #define __BOOST_DI_DEPRECATED(...) [[deprecated(__VA_ARGS__)]] #define __BOOST_DI_TYPE_WKND(T) #define __BOOST_DI_ACCESS_WKND private #define __BOOST_DI_VARIABLE_TEMPLATE_INIT_WKND \ {} #elif defined(_MSC_VER) #define __MSVC__ #if !defined(__has_include) #define __has_include(...) 0 #endif #define __BOOST_DI_UNUSED #define __BOOST_DI_DEPRECATED(...) __declspec(deprecated(__VA_ARGS__)) #define __BOOST_DI_TYPE_WKND(T) (T &&) #define __BOOST_DI_ACCESS_WKND public #define __BOOST_DI_VARIABLE_TEMPLATE_INIT_WKND #endif #if !defined(__has_builtin) #define __has_builtin(...) 0 #endif #if !defined(__has_extension) #define __has_extension(...) 0 #endif #if defined(__CLANG__) #if (!BOOST_DI_CFG_DIAGNOSTICS_LEVEL) #pragma clang diagnostic error "-Wdeprecated-declarations" #else #pragma clang diagnostic warning "-Wdeprecated-declarations" #endif #pragma clang diagnostic push #pragma clang diagnostic error "-Wundefined-inline" #pragma clang diagnostic error "-Wundefined-internal" #pragma clang diagnostic ignored "-Wmissing-field-initializers" #elif defined(__GCC__) #pragma GCC diagnostic push #pragma GCC diagnostic error "-Wdeprecated-declarations" #if (__GNUC__ < 6) #pragma GCC diagnostic error "-Werror" #endif #elif defined(__MSVC__) #pragma warning(disable : 4503) #pragma warning(disable : 4822) #pragma warning(disable : 4505) #endif #if defined(_LIBCPP_VERSION) #define NAMESPACE_STD_BEGIN _LIBCPP_BEGIN_NAMESPACE_STD { #else #define NAMESPACE_STD_BEGIN namespace std { #endif #if defined(_LIBCPP_VERSION) #define NAMESPACE_STD_END _LIBCPP_END_NAMESPACE_STD #else #define NAMESPACE_STD_END } #endif #if __has_include(<__config>) #include <__config> #endif #if __has_include() #include #else NAMESPACE_STD_BEGIN template class shared_ptr; template class weak_ptr; template class unique_ptr; NAMESPACE_STD_END #endif #if __has_include() #include #else NAMESPACE_STD_BEGIN template class vector; NAMESPACE_STD_END #endif #if __has_include() #include #else NAMESPACE_STD_BEGIN template class set; NAMESPACE_STD_END #endif #if __has_include() #include #else NAMESPACE_STD_BEGIN template class initializer_list; NAMESPACE_STD_END #endif #if __has_include() #include #else NAMESPACE_STD_BEGIN template class tuple; NAMESPACE_STD_END #endif #if __has_include() #include #else NAMESPACE_STD_BEGIN template class move_iterator; NAMESPACE_STD_END #endif #if __has_include() #include #else NAMESPACE_STD_BEGIN template struct char_traits; NAMESPACE_STD_END #endif // clang-format off #if __has_include() // clang-format on #include #else namespace boost { template class shared_ptr; } #endif BOOST_DI_NAMESPACE_BEGIN struct _ { _(...) {} }; namespace aux { using swallow = int[]; template using owner = T; template struct valid { using type = int; }; template using valid_t = typename valid::type; template struct type {}; struct none_type {}; template struct non_type {}; template struct always { static constexpr auto value = true; }; template struct never { static constexpr auto value = false; }; template struct identity { using type = T; }; template struct type_list { using type = type_list; }; template struct bool_list { using type = bool_list; }; template struct pair { using type = pair; using first = T1; using second = T2; }; template struct inherit : Ts... { using type = inherit; }; template struct join { using type = type_list<>; }; template struct join { using type = T; }; template struct join, type_list, Ts...> : join, Ts...> {}; template struct join, type_list, type_list, type_list, type_list, type_list, type_list, type_list, type_list, type_list, type_list, type_list, type_list, type_list, type_list, type_list, type_list, Us...> : join, Us...> {}; template using join_t = typename join::type; template struct index_sequence { using type = index_sequence; }; #if __has_builtin(__make_integer_seq) template struct integer_sequence { using type = index_sequence; }; template struct make_index_sequence_impl { using type = typename __make_integer_seq::type; }; #else template struct build_index_sequence; template struct build_index_sequence, index_sequence> { using type = index_sequence; }; template struct make_index_sequence_impl { using type = typename build_index_sequence::type, typename make_index_sequence_impl::type>::type; }; template <> struct make_index_sequence_impl<0> : index_sequence<> {}; template <> struct make_index_sequence_impl<1> : index_sequence<0> {}; template <> struct make_index_sequence_impl<2> : index_sequence<0, 1> {}; template <> struct make_index_sequence_impl<3> : index_sequence<0, 1, 2> {}; template <> struct make_index_sequence_impl<4> : index_sequence<0, 1, 2, 3> {}; template <> struct make_index_sequence_impl<5> : index_sequence<0, 1, 2, 3, 4> {}; template <> struct make_index_sequence_impl<6> : index_sequence<0, 1, 2, 3, 4, 5> {}; template <> struct make_index_sequence_impl<7> : index_sequence<0, 1, 2, 3, 4, 5, 6> {}; template <> struct make_index_sequence_impl<8> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7> {}; template <> struct make_index_sequence_impl<9> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7, 8> {}; template <> struct make_index_sequence_impl<10> : index_sequence<0, 1, 2, 3, 4, 5, 6, 7, 8, 9> {}; #endif template using make_index_sequence = typename make_index_sequence_impl::type; } namespace placeholders { __BOOST_DI_UNUSED static const struct arg { } _{}; } template struct named {}; struct no_name { constexpr auto operator()() const noexcept { return ""; } }; template struct ctor_traits; template struct self {}; struct ignore_policies {}; namespace core { template struct any_type_fwd; template struct any_type_ref_fwd; template struct any_type_1st_fwd; template struct any_type_1st_ref_fwd; struct dependency_base {}; struct injector_base {}; template struct dependency__ : T { using T::create; using T::is_referable; using T::try_create; }; template struct injector__ : T { using T::cfg; using T::create_impl; using T::create_successful_impl; #if defined(__MSVC__) template using is_creatable = typename T::template is_creatable; template using try_create = typename T::template try_create; #else using T::is_creatable; using T::try_create; #endif }; template struct array; struct deduced {}; struct none {}; template class dependency; } namespace scopes { class deduce; class instance; class singleton; class unique; } #define __BOOST_DI_REQUIRES(...) typename ::boost::ext::di::v1_3_0::aux::enable_if<__VA_ARGS__, int>::type #define __BOOST_DI_REQUIRES_MSG(...) typename ::boost::ext::di::v1_3_0::aux::concept_check<__VA_ARGS__>::type namespace aux { template T&& declval(); template struct integral_constant { using type = integral_constant; static constexpr T value = V; }; using true_type = integral_constant; using false_type = integral_constant; template struct conditional { using type = T; }; template struct conditional { using type = F; }; template using conditional_t = typename conditional::type; template struct enable_if {}; template struct enable_if { using type = T; }; template using enable_if_t = typename enable_if::type; template struct concept_check { static_assert(T::value, "constraint not satisfied"); }; template <> struct concept_check { using type = int; }; template struct remove_reference { using type = T; }; template struct remove_reference { using type = T; }; template struct remove_reference { using type = T; }; template using remove_reference_t = typename remove_reference::type; template struct remove_pointer { using type = T; }; template struct remove_pointer { using type = T; }; template using remove_pointer_t = typename remove_pointer::type; template struct remove_smart_ptr { using type = T; }; template struct remove_smart_ptr> { using type = T; }; template struct remove_smart_ptr> { using type = T; }; template struct remove_smart_ptr> { using type = T; }; template struct remove_smart_ptr> { using type = T; }; template using remove_smart_ptr_t = typename remove_smart_ptr::type; template struct remove_qualifiers { using type = T; }; template struct remove_qualifiers { using type = T; }; template struct remove_qualifiers { using type = T; }; template struct remove_qualifiers { using type = T; }; template struct remove_qualifiers { using type = T; }; template struct remove_qualifiers { using type = T; }; template struct remove_qualifiers { using type = T; }; template struct remove_qualifiers { using type = T; }; template struct remove_qualifiers { using type = T; }; template struct remove_qualifiers { using type = T; }; template using remove_qualifiers_t = typename remove_qualifiers::type; template struct remove_extent { using type = T; }; template struct remove_extent { using type = T; }; template using remove_extent_t = typename remove_extent::type; template struct deref_type { using type = T; }; template struct deref_type> { using type = remove_qualifiers_t::type>; }; template struct deref_type> { using type = remove_qualifiers_t::type>; }; template struct deref_type> { using type = remove_qualifiers_t::type>; }; template struct deref_type> { using type = remove_qualifiers_t::type>; }; template struct deref_type> { using type = core::array::type>>; }; template struct deref_type> { using type = core::array::type>>; }; template struct deref_type> { using type = core::array::type>>; }; template using decay_t = typename deref_type>::type; template struct is_same : false_type {}; template struct is_same : true_type {}; template struct is_base_of : integral_constant {}; template struct is_class : integral_constant {}; template struct is_abstract : integral_constant {}; template struct is_polymorphic : integral_constant {}; template struct is_final : integral_constant {}; template using is_valid_expr = true_type; #if __has_extension(is_constructible) && !((__clang_major__ == 3) && (__clang_minor__ == 5)) template using is_constructible = integral_constant; #else template decltype(void(T(declval()...)), true_type{}) test_is_constructible(int); template false_type test_is_constructible(...); template struct is_constructible : decltype(test_is_constructible(0)) {}; #endif template using is_constructible_t = typename is_constructible::type; template decltype(void(T{declval()...}), true_type{}) test_is_braces_constructible(int); template false_type test_is_braces_constructible(...); template using is_braces_constructible = decltype(test_is_braces_constructible(0)); template using is_braces_constructible_t = typename is_braces_constructible::type; #if defined(__MSVC__) template struct is_copy_constructible : integral_constant {}; template struct is_default_constructible : integral_constant {}; #else template using is_copy_constructible = is_constructible; template using is_default_constructible = is_constructible; #endif #if defined(__CLANG__) || defined(__MSVC__) template struct is_convertible : integral_constant {}; #else struct test_is_convertible__ { template static void test(T); }; template (declval()))> true_type test_is_convertible(int); template false_type test_is_convertible(...); template using is_convertible = decltype(test_is_convertible(0)); #endif template > using is_narrowed = integral_constant::value && !is_class::value && !is_same::value>; template struct is_array : false_type {}; template struct is_array : true_type {}; template true_type is_complete_impl(int); template false_type is_complete_impl(...); template struct is_complete : decltype(is_complete_impl(0)) {}; template is_base_of is_a_impl(int); template false_type is_a_impl(...); template struct is_a : decltype(is_a_impl(0)) {}; template struct is_unique_impl; template struct not_unique : false_type { using type = not_unique; }; template <> struct not_unique<> : true_type { using type = not_unique; }; template struct is_unique_impl : not_unique<> {}; template struct is_unique_impl : conditional_t, T1>::value, not_unique, is_unique_impl>, Ts...>> {}; template using is_unique = is_unique_impl; template struct unique; template struct unique, T, Ts...> : conditional_t, inherit...>>::value, unique, Ts...>, unique, Ts...>> {}; template struct unique> : type_list {}; template using unique_t = typename unique, Ts...>::type; false_type has_shared_ptr__(...); #if !defined(BOOST_DI_DISABLE_SHARED_PTR_DEDUCTION) template auto has_shared_ptr__(T&&) -> is_valid_expr{})>; #endif template decltype(::boost::ext::di::v1_3_0::aux::declval().operator()(::boost::ext::di::v1_3_0::aux::declval()...), ::boost::ext::di::v1_3_0::aux::true_type()) is_invocable_impl(int); template ::boost::ext::di::v1_3_0::aux::false_type is_invocable_impl(...); template struct is_invocable : decltype(is_invocable_impl(0)) {}; struct callable_base_impl { void operator()(...) {} }; template struct callable_base : callable_base_impl, aux::conditional_t::value && !aux::is_final::value, T, aux::none_type> {}; template aux::false_type is_callable_impl(T*, aux::non_type* = 0); aux::true_type is_callable_impl(...); template struct is_callable : decltype(is_callable_impl(aux::declval*>())) {}; template struct is_empty_expr : false_type {}; template #if defined(__MSVC__) struct is_empty_expr()())>> : integral_constant { }; #else struct is_empty_expr()), decltype(declval()())>> : true_type { }; #endif template struct function_traits; template struct function_traits { using result_type = R; using args = type_list; }; template struct function_traits { using result_type = R; using args = type_list; }; template struct function_traits { using result_type = R; using args = type_list; }; template struct function_traits { using result_type = R; using args = type_list; }; template using function_traits_t = typename function_traits::args; } namespace core { template ::type> struct bindings_impl; template struct bindings_impl { using type = typename T::deps; }; template struct bindings_impl { using type = aux::type_list; }; #if defined(__MSVC__) template struct bindings : aux::join_t::type...> {}; template using bindings_t = typename bindings::type; #else template using bindings_t = aux::join_t::type...>; #endif } namespace concepts { template struct type_ { template struct named { struct is_bound_more_than_once : aux::false_type {}; }; struct is_bound_more_than_once : aux::false_type {}; struct is_neither_a_dependency_nor_an_injector : aux::false_type {}; struct has_disallowed_qualifiers : aux::false_type {}; struct is_abstract : #if (BOOST_DI_CFG_DIAGNOSTICS_LEVEL >= 2) // clang-format off decltype( T{} ), // clang-format on #endif aux::false_type { }; template struct is_not_related_to : aux::false_type {}; }; template struct any_of : aux::false_type {}; template struct is_supported : aux::is_same::value...>, aux::bool_list<(aux::is_constructible::value && (aux::is_a::value || aux::is_a::value || aux::is_empty_expr::value))...>> { }; template struct get_not_supported; template struct get_not_supported { using type = T; }; template struct get_not_supported : aux::conditional::value || aux::is_a::value, typename get_not_supported::type, T> {}; template struct is_unique; template struct unique_dependency : aux::type {}; template struct unique_dependency::value)> : aux::pair, typename T::priority> {}; template struct is_unique> : aux::is_unique::type...> {}; template struct get_is_unique_error_impl : aux::true_type {}; template struct get_is_unique_error_impl, TPriority>>> { using type = typename type_::template named::is_bound_more_than_once; }; template struct get_is_unique_error_impl, TPriority>>> { using type = typename type_::is_bound_more_than_once; }; template struct get_is_unique_error_impl> { using type = typename type_::is_bound_more_than_once; }; template struct get_is_unique_error; template struct get_is_unique_error> : get_is_unique_error_impl::type...>::type> {}; template using boundable_bindings = aux::conditional_t::value, typename get_is_unique_error>::type, typename type_::type>::is_neither_a_dependency_nor_an_injector>; template struct get_any_of_error : aux::conditional::value...>, aux::bool_list::value...>>::value, aux::true_type, any_of> {}; template struct is_related { static constexpr auto value = true; }; template struct is_related { static constexpr auto value = aux::is_base_of::value || (aux::is_convertible::value && !aux::is_narrowed::value); }; template struct is_abstract { static constexpr auto value = false; }; template struct is_abstract { static constexpr auto value = aux::is_abstract::value; }; auto boundable_impl(any_of<>&&) -> aux::true_type; template auto boundable_impl(any_of&&) -> aux::conditional_t>::value, decltype(boundable_impl(aux::declval>())), typename type_::has_disallowed_qualifiers>; template using boundable_impl__ = aux::conditional_t< is_related::value && aux::is_complete::value, I, T>::value, aux::conditional_t::value, T>::value, typename type_::is_abstract, aux::true_type>, typename type_::template is_not_related_to>; template auto boundable_impl(I&&, T&&) -> aux::conditional_t>::value || !aux::is_complete::value, boundable_impl__, typename type_::has_disallowed_qualifiers>; template auto boundable_impl(I&&, T&&, aux::valid<>&&) -> aux::conditional_t::value && aux::is_complete::value, I, T>::value, aux::true_type, typename type_::template is_not_related_to>; template auto boundable_impl(I*[], T&&) -> aux::conditional_t>::value, boundable_impl__, typename type_::has_disallowed_qualifiers>; template auto boundable_impl(I[], T&&) -> aux::conditional_t>::value, boundable_impl__, typename type_::has_disallowed_qualifiers>; template auto boundable_impl(aux::type_list&&) -> boundable_bindings; template auto boundable_impl(concepts::any_of&&, T&&) -> typename get_any_of_error(), aux::declval()))...>::type; template auto boundable_impl(aux::type&&) -> typename get_is_unique_error_impl::type>::type; aux::true_type boundable_impl(...); template struct boundable__ { using type = decltype(boundable_impl(aux::declval()...)); }; template using boundable = typename boundable__::type; } namespace type_traits { struct stack {}; struct heap {}; template struct memory_traits { using type = stack; }; template struct memory_traits { using type = heap; }; template struct memory_traits { using type = typename memory_traits::type; }; template struct memory_traits> { using type = heap; }; template struct memory_traits> { using type = heap; }; template struct memory_traits> { using type = heap; }; template struct memory_traits> { using type = heap; }; template struct memory_traits::value)> { using type = heap; }; } namespace concepts { template struct scope { struct is_referable {}; struct try_create {}; struct create {}; template struct requires_ : aux::false_type {}; }; template struct scope__ { template struct scope { template using is_referable = aux::true_type; template T try_create(const TProvider&); template T create(const TProvider&); }; }; template struct config__ { template struct scope_traits { using type = scope__; }; template struct memory_traits { using type = type_traits::heap; }; }; template struct provider__ { using config = config__; template aux::conditional_t::value, T, T*> try_get(const TMemory& = {}) const; template T* get(const TMemory& = {}) const { return nullptr; } config& cfg() const; }; template typename scope::template requires_::is_referable, typename scope<_, _>::try_create, typename scope<_, _>::create> scopable_impl(...); template auto scopable_impl(T&&) -> aux::is_valid_expr::template is_referable<_, config__<_>>, decltype(T::template scope<_, _>::template try_create<_, _>(provider__<_>{})), decltype(aux::declval>().template create<_, _>(provider__<_>{}))>; template struct scopable__ { using type = decltype(scopable_impl(aux::declval())); }; template using scopable = typename scopable__::type; } namespace core { template > struct pool; template using pool_t = pool>; template struct pool> : TArgs... { template explicit pool(Ts... args) noexcept : Ts(static_cast(args))... {} template pool(const aux::type_list&, TPool p) noexcept : pool(static_cast(p)...) { (void)p; } template pool& operator=(T&& other) noexcept { (void)aux::swallow{0, (static_cast(*this).operator=(static_cast(other)), 0)...}; return *this; } }; } #if !defined(BOOST_DI_CFG_CTOR_LIMIT_SIZE) #define BOOST_DI_CFG_CTOR_LIMIT_SIZE 10 #endif namespace type_traits { template struct is_injectable : ::boost::ext::di::v1_3_0::aux::false_type {}; template struct is_injectable> : ::boost::ext::di::v1_3_0::aux::true_type {}; struct direct {}; struct uniform {}; template using get = T; template