6#include <userver/components/component_base.hpp>
7#include <userver/components/component_config.hpp>
8#include <userver/components/component_context.hpp>
9#include <userver/formats/common/meta.hpp>
11USERVER_NAMESPACE_BEGIN
19constexpr std::string_view ContainerName(
Of<
void>) {
return {}; }
27template <
typename T,
typename =
void>
28struct ContainerHasName : std::false_type {};
31struct ContainerHasName<T, utils::void_t<
decltype(ContainerName(
Of<T>()))>> : std::true_type {};
34constexpr std::string_view GetContainerName()
36 if constexpr (ContainerHasName<T>::value) {
37 return ContainerName(
Of<T>());
39 static_assert(!
sizeof(T),
"Container name is not registered. Forgot to define ContainerName(Of<T>)?");
45struct DependencyLocator {
46 const ComponentConfig& config;
47 const ComponentContext& context;
50 using LocateDependencyResult =
decltype(LocateDependency(
51 WithType<std::decay_t<T>>{},
52 std::declval<
const ComponentConfig&>(),
53 std::declval<
const ComponentContext&>()
57 static constexpr bool kIsReference = std::is_reference_v<LocateDependencyResult<T>>;
60 static constexpr bool kIsLocatable =
61 !std::is_same_v<std::decay_t<T>, std::decay_t<U>>
62 && !!
sizeof(LocateDependencyResult<T>)
65 template <
typename T,
typename = std::enable_if_t<!kIsReference<T> && kIsLocatable<T>>>
67 return LocateDependency(WithType<std::decay_t<T>>{}, config, context);
70 template <
typename T,
typename = std::enable_if_t<kIsReference<T> && kIsLocatable<T>>>
72 return LocateDependency(WithType<std::decay_t<T>>{}, config, context);
89std::enable_if_t<formats::common::impl::kHasParse<yaml_config::YamlConfig, T> && std::is_class_v<T>, T>
92 return config.As<T>();
96std::enable_if_t<impl::ContainerHasName<T>::value, T&> LocateDependency(
98 const ComponentConfig&,
99 const ComponentContext& context
102 return context.FindComponent<Container<T>>().Get();
106std::enable_if_t<std::is_base_of_v<RawComponentBase, T>, T&> LocateDependency(
108 const ComponentConfig&,
109 const ComponentContext& context
112 return context.FindComponent<T>();
144class Container final :
public ComponentBase {
146 Container(
const ComponentConfig& config,
const ComponentContext& context)
147 : ComponentBase(config, context),
148 content_(Build(config, context))
151 T& Get() {
return content_; }
153 static constexpr auto kConfigFileMode = ConfigFileMode::kNotRequired;
155 static constexpr std::string_view kName = impl::GetContainerName<T>();
158 static T Build(
const ComponentConfig& config,
const ComponentContext& context)
160 using Arg = impl::DependencyLocator<T>;
161 Arg arg{config, context};
165 if constexpr (std::is_constructible<T>::value) {
167 }
else if constexpr (std::is_constructible<T, Arg>::value) {
169 }
else if constexpr (std::is_constructible<T, Arg, Arg>::value) {
171 }
else if constexpr (std::is_constructible<T, Arg, Arg, Arg>::value) {
172 return T(arg, arg, arg);
173 }
else if constexpr (std::is_constructible<T, Arg, Arg, Arg, Arg>::value) {
174 return T(arg, arg, arg, arg);
175 }
else if constexpr (std::is_constructible<T, Arg, Arg, Arg, Arg, Arg>::value) {
176 return T(arg, arg, arg, arg, arg);
177 }
else if constexpr (std::is_constructible<T, Arg, Arg, Arg, Arg, Arg, Arg>::value) {
178 return T(arg, arg, arg, arg, arg, arg);
179 }
else if constexpr (std::is_constructible<T, Arg, Arg, Arg, Arg, Arg, Arg, Arg>::value) {
180 return T(arg, arg, arg, arg, arg, arg, arg);
181 }
else if constexpr (std::is_constructible<T, Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg>::value) {
182 return T(arg, arg, arg, arg, arg, arg, arg, arg);
183 }
else if constexpr (std::is_constructible<T, Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg>::value) {
184 return T(arg, arg, arg, arg, arg, arg, arg, arg, arg);
185 }
else if constexpr (std::is_constructible<T, Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg, Arg>::value) {
186 return T(arg, arg, arg, arg, arg, arg, arg, arg, arg, arg);
190 "Failed to find an appropriate version of T::T(...). Please check that T has a constructor with "
191 "arguments of containerized types or locatable via LocateDependency()."