blob: 25e1509e6184c39a0d5c1c7cdcc15d0e60b90ab9 [file] [log] [blame]
Marco Poletti4d39c582014-11-24 18:33:48 +00001/*
2 * Copyright 2014 Google Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef FRUIT_COMPONENT_FUNCTORS_DEFN_H
18#define FRUIT_COMPONENT_FUNCTORS_DEFN_H
19
Marco Polettif2895102016-01-30 13:38:37 +000020#include <fruit/component.h>
Marco Poletti4d39c582014-11-24 18:33:48 +000021
Marco Polettif2895102016-01-30 13:38:37 +000022#include <fruit/impl/injection_errors.h>
23#include <fruit/impl/injection_debug_errors.h>
24#include <fruit/impl/storage/component_storage.h>
Marco Poletti3e576c22016-06-19 16:34:08 +010025#include <fruit/impl/storage/injector_storage.h>
Marco Poletti4d39c582014-11-24 18:33:48 +000026
27#include <memory>
28
Marco Polettib9f19bf2015-01-01 17:07:25 +010029/*********************************************************************************************************************************
30 This file contains functors that take a Comp and return a struct Op with the form:
31 struct {
32 using Result = Comp1;
33 void operator()(ComponentStorage& storage) {...}
34 }
35*********************************************************************************************************************************/
36
Marco Poletti4d39c582014-11-24 18:33:48 +000037namespace fruit {
Marco Poletti4d39c582014-11-24 18:33:48 +000038namespace impl {
Marco Polettia19fd1e2015-03-07 18:50:37 +000039namespace meta {
40
41struct GetResult {
42 template <typename F>
43 struct apply {
44 using type = typename F::Result;
45 };
46};
Marco Poletti4d39c582014-11-24 18:33:48 +000047
Marco Poletti010daa62015-07-06 01:15:12 +010048// Call(ComponentFunctor(F, Args...), Comp)
49// is equivalent to:
50// F(Comp, Args...)
51struct ComponentFunctor {
52 template <typename F, typename... Args>
53 struct apply {
54 struct type {
55 template <typename Comp>
56 struct apply {
57 using type = F(Comp, Args...);
58 };
59 };
60 };
61};
62
Marco Poletti1ff06b32015-07-19 20:06:19 +010063struct NoOpComponentFunctor {
64 using Result = void;
65 template <typename... Types>
66 void operator()(ComponentStorage&, const Types&...) {}
67};
68
Marco Poletti36253c92015-07-19 17:12:47 +010069struct ComponentFunctorIdentity {
Marco Polettica50c3a2014-12-31 18:26:52 +010070 template <typename Comp>
71 struct apply {
Marco Polettib9f19bf2015-01-01 17:07:25 +010072 struct type {
73 using Result = Comp;
Marco Polettia19fd1e2015-03-07 18:50:37 +000074 void operator()(ComponentStorage&) {}
Marco Polettib9f19bf2015-01-01 17:07:25 +010075 };
Marco Polettica50c3a2014-12-31 18:26:52 +010076 };
77};
78
Marco Poletti36253c92015-07-19 17:12:47 +010079struct Compose2ComponentFunctors {
80 template <typename F1, typename F2>
81 struct apply {
82 struct type {
83 template <typename Comp>
84 struct apply {
85 using Op1 = F1(Comp);
86 using Op2 = F2(GetResult(Op1));
87 struct Op {
88 using Result = Eval<GetResult(Op2)>;
89 void operator()(ComponentStorage& storage) {
90 Eval<Op1>()(storage);
91 Eval<Op2>()(storage);
92 }
93 };
94 using type = PropagateError(Op1,
95 PropagateError(Op2,
96 Op));
97 };
98 };
99 };
100};
101
Marco Poletti010daa62015-07-06 01:15:12 +0100102// ComposeFunctors(F1,..,Fn) returns a functor that executes F1,..,Fn in order (stopping at the
103// first Error).
104struct ComposeFunctors {
105 template <typename... Functors>
Marco Poletti36253c92015-07-19 17:12:47 +0100106 struct apply {
107 using type = Fold(Compose2ComponentFunctors, ComponentFunctorIdentity, Functors...);
Marco Polettib9f19bf2015-01-01 17:07:25 +0100108 };
109};
Marco Polettica50c3a2014-12-31 18:26:52 +0100110
Marco Polettie8443552016-02-07 10:25:39 +0000111// ReverseComposeFunctors(T1, ..., Tn) is equivalent to ComposeFunctors(Tn, ..., T1), but it's more
112// efficient when all of the following must be evaluated:
113// ReverseComposeFunctors<T1>
114// ReverseComposeFunctors<T2, T1>
115// ReverseComposeFunctors<T3, T2, T1>
116// In that case, this implementation shares many more instantiations with previous invocations
117struct ReverseComposeFunctors {
118 template <typename... Functors>
119 struct apply {
120 using type = ComponentFunctorIdentity;
121 };
122
123 template <typename Functor>
124 struct apply<Functor> {
125 using type = Functor;
126 };
127
128 template <typename Functor, typename... Functors>
129 struct apply<Functor, Functors...> {
130 using type = Compose2ComponentFunctors(ReverseComposeFunctors(Functors...), Functor);
131 };
132};
133
Marco Polettica50c3a2014-12-31 18:26:52 +0100134struct EnsureProvidedType;
135
Marco Poletti4d39c582014-11-24 18:33:48 +0000136struct EnsureProvidedTypes;
137
Marco Poletti2edd8662014-12-31 16:06:07 +0100138// Doesn't actually bind in ComponentStorage. The binding is added later (if needed) using ProcessInterfaceBinding.
Marco Poletti2edd8662014-12-31 16:06:07 +0100139struct AddDeferredInterfaceBinding {
Marco Poletti010daa62015-07-06 01:15:12 +0100140 template <typename Comp, typename AnnotatedI, typename AnnotatedC>
Marco Polettica50c3a2014-12-31 18:26:52 +0100141 struct apply {
Marco Poletti36253c92015-07-19 17:12:47 +0100142 using Comp1 = ConsComp(typename Comp::RsSuperset,
Marco Poletti010daa62015-07-06 01:15:12 +0100143 typename Comp::Ps,
Marco Poletti42c3b7c2016-05-22 09:32:36 +0100144#ifndef FRUIT_NO_LOOP_CHECK
Marco Poletti010daa62015-07-06 01:15:12 +0100145 typename Comp::Deps,
Marco Poletti42c3b7c2016-05-22 09:32:36 +0100146#endif
Marco Polettiec5c5202015-07-26 11:18:44 +0100147 PushFront(typename Comp::InterfaceBindings,
148 Pair<AnnotatedI, AnnotatedC>),
Marco Poletti010daa62015-07-06 01:15:12 +0100149 typename Comp::DeferredBindingFunctors);
150 struct Op {
Marco Polettie9c143b2015-03-08 16:46:50 +0000151 // Note that we do NOT call AddProvidedType here. We'll only know the right required type
152 // when the binding will be used.
Marco Poletti3b95a512015-07-11 13:43:39 +0100153 using Result = Eval<Comp1>;
Marco Polettie9c143b2015-03-08 16:46:50 +0000154 void operator()(ComponentStorage&) {}
Marco Polettica50c3a2014-12-31 18:26:52 +0100155 };
Marco Poletti010daa62015-07-06 01:15:12 +0100156 using I = RemoveAnnotations(AnnotatedI);
157 using C = RemoveAnnotations(AnnotatedC);
Marco Poletti6026b752016-02-21 14:30:31 +0000158 using type = If(IsSame(I, C),
159 ConstructError(InterfaceBindingToSelfErrorTag, C),
160 If(Not(IsBaseOf(I, C)),
Marco Poletti010daa62015-07-06 01:15:12 +0100161 ConstructError(NotABaseClassOfErrorTag, I, C),
Marco Poletti072fb362016-12-10 18:49:08 +0000162 If(Not(IsSame(I, NormalizeType(I))),
163 ConstructError(NonClassTypeErrorTag, I, NormalizeType(I)),
164 If(Not(IsSame(C, NormalizeType(C))),
165 // We handle this case too, just to be on the safe side, but this should never happen.
166 ConstructError(NonClassTypeErrorTag, C, NormalizeType(C)),
Marco Poletti417e0452016-11-20 14:23:37 +0000167 If(IsInSet(AnnotatedI, typename Comp::Ps),
168 ConstructError(TypeAlreadyBoundErrorTag, AnnotatedI),
169 If(MapContainsKey(typename Comp::InterfaceBindings, AnnotatedI),
170 ConstructError(TypeAlreadyBoundErrorTag, AnnotatedI),
Marco Poletti072fb362016-12-10 18:49:08 +0000171 Op))))));
Marco Poletti4d39c582014-11-24 18:33:48 +0000172 };
173};
174
Marco Poletti2edd8662014-12-31 16:06:07 +0100175struct ProcessInterfaceBinding {
Marco Poletti010daa62015-07-06 01:15:12 +0100176 template <typename Comp, typename AnnotatedI, typename AnnotatedC>
Marco Polettica50c3a2014-12-31 18:26:52 +0100177 struct apply {
Marco Polettidff77482016-03-26 11:20:10 +0000178 using R = AddProvidedTypeIgnoringInterfaceBindings(Comp, AnnotatedI, Vector<AnnotatedC>);
Marco Poletti010daa62015-07-06 01:15:12 +0100179 struct Op {
Marco Polettie9c143b2015-03-08 16:46:50 +0000180 // This must be here (and not in AddDeferredInterfaceBinding) because the binding might be
181 // used to bind functors instead, so we might never need to add C to the requirements.
Marco Poletti3b95a512015-07-11 13:43:39 +0100182 using Result = Eval<R>;
Marco Polettib9f19bf2015-01-01 17:07:25 +0100183 void operator()(ComponentStorage& storage) {
Marco Poletti010daa62015-07-06 01:15:12 +0100184 storage.addBinding(InjectorStorage::createBindingDataForBind<
Marco Poletti3b95a512015-07-11 13:43:39 +0100185 UnwrapType<AnnotatedI>, UnwrapType<AnnotatedC>>());
Marco Polettib9f19bf2015-01-01 17:07:25 +0100186 };
Marco Polettica50c3a2014-12-31 18:26:52 +0100187 };
Marco Poletti36253c92015-07-19 17:12:47 +0100188 using type = PropagateError(R,
Marco Poletti010daa62015-07-06 01:15:12 +0100189 Op);
Marco Poletti4d39c582014-11-24 18:33:48 +0000190 };
191};
192
Marco Poletti2edd8662014-12-31 16:06:07 +0100193struct AddInterfaceMultibinding {
Marco Poletti010daa62015-07-06 01:15:12 +0100194 template <typename Comp, typename AnnotatedI, typename AnnotatedC>
Marco Polettica50c3a2014-12-31 18:26:52 +0100195 struct apply {
Marco Poletti010daa62015-07-06 01:15:12 +0100196 using I = RemoveAnnotations(AnnotatedI);
197 using C = RemoveAnnotations(AnnotatedC);
198 using R = AddRequirements(Comp, Vector<AnnotatedC>);
199 struct Op {
Marco Poletti3b95a512015-07-11 13:43:39 +0100200 using Result = Eval<R>;
Marco Polettib9f19bf2015-01-01 17:07:25 +0100201 void operator()(ComponentStorage& storage) {
Marco Poletti010daa62015-07-06 01:15:12 +0100202 storage.addMultibinding(InjectorStorage::createMultibindingDataForBinding<
Marco Poletti3b95a512015-07-11 13:43:39 +0100203 UnwrapType<AnnotatedI>, UnwrapType<AnnotatedC>>());
Marco Polettib9f19bf2015-01-01 17:07:25 +0100204 };
Marco Polettica50c3a2014-12-31 18:26:52 +0100205 };
Marco Poletti010daa62015-07-06 01:15:12 +0100206 using type = If(Not(IsBaseOf(I, C)),
207 ConstructError(NotABaseClassOfErrorTag, I, C),
Marco Poletti36253c92015-07-19 17:12:47 +0100208 Op);
Marco Poletti4d39c582014-11-24 18:33:48 +0000209 };
210};
211
Marco Poletti31f638a2015-05-10 21:21:25 +0100212template <typename AnnotatedSignature, typename Lambda, typename OptionalAnnotatedI>
Marco Poletticc97a162015-05-10 12:10:12 +0100213struct PostProcessRegisterProviderHelper;
214
Marco Poletti31f638a2015-05-10 21:21:25 +0100215template <typename AnnotatedSignature, typename Lambda, typename AnnotatedI>
Marco Poletti010daa62015-07-06 01:15:12 +0100216struct PostProcessRegisterProviderHelper;
217
218template <typename AnnotatedSignature, typename Lambda, typename AnnotatedI>
219struct PostProcessRegisterProviderHelper<AnnotatedSignature, Lambda, Type<AnnotatedI>> {
Marco Poletti4d39c582014-11-24 18:33:48 +0000220 inline void operator()(ComponentStorage& component) {
Marco Poletti010daa62015-07-06 01:15:12 +0100221 component.addBinding(InjectorStorage::createBindingDataForProvider<
222 AnnotatedSignature, Lambda>());
223 component.addCompressedBinding(InjectorStorage::createBindingDataForCompressedProvider<
224 AnnotatedSignature, Lambda, AnnotatedI>());
Marco Poletti4d39c582014-11-24 18:33:48 +0000225 }
226};
227
Marco Poletti31f638a2015-05-10 21:21:25 +0100228template <typename AnnotatedSignature, typename Lambda>
229struct PostProcessRegisterProviderHelper<AnnotatedSignature, Lambda, None> {
Marco Poletti4d39c582014-11-24 18:33:48 +0000230 inline void operator()(ComponentStorage& component) {
Marco Poletti010daa62015-07-06 01:15:12 +0100231 component.addBinding(InjectorStorage::createBindingDataForProvider<
232 AnnotatedSignature, Lambda>());
Marco Poletti4d39c582014-11-24 18:33:48 +0000233 }
234};
235
Marco Poletti4d39c582014-11-24 18:33:48 +0000236// T can't be any injectable type, it must match the return type of the provider in one of
237// the registerProvider() overloads in ComponentStorage.
Marco Polettie9c143b2015-03-08 16:46:50 +0000238struct PostProcessRegisterProvider {
Marco Poletti010daa62015-07-06 01:15:12 +0100239 template <typename Comp, typename AnnotatedSignature, typename Lambda>
Marco Polettica50c3a2014-12-31 18:26:52 +0100240 struct apply {
Marco Poletti36253c92015-07-19 17:12:47 +0100241 using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature));
Marco Poletti1e44d552017-05-20 14:10:38 +0100242 using OptionalAnnotatedI = FindValueInMap(typename Comp::InterfaceBindings, AnnotatedC);
Marco Poletti010daa62015-07-06 01:15:12 +0100243 struct Op {
Marco Polettie9c143b2015-03-08 16:46:50 +0000244 using Result = Comp;
Marco Polettib9f19bf2015-01-01 17:07:25 +0100245 void operator()(ComponentStorage& storage) {
Marco Poletti010daa62015-07-06 01:15:12 +0100246 PostProcessRegisterProviderHelper<
Marco Poletti3b95a512015-07-11 13:43:39 +0100247 UnwrapType<AnnotatedSignature>, UnwrapType<Lambda>, Eval<OptionalAnnotatedI>>()(storage);
Marco Polettib9f19bf2015-01-01 17:07:25 +0100248 }
249 };
Marco Poletti010daa62015-07-06 01:15:12 +0100250 using type = Op;
Marco Polettid8943a82015-01-01 15:57:16 +0100251 };
252};
253
Marco Polettie9c143b2015-03-08 16:46:50 +0000254struct PreProcessRegisterProvider {
Marco Poletti010daa62015-07-06 01:15:12 +0100255 template <typename Comp, typename AnnotatedSignature, typename Lambda>
Marco Polettie9c143b2015-03-08 16:46:50 +0000256 struct apply {
Marco Poletti36253c92015-07-19 17:12:47 +0100257 using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature);
258 using SignatureFromLambda = FunctionSignature(Lambda);
Marco Poletti010daa62015-07-06 01:15:12 +0100259
Marco Poletti36253c92015-07-19 17:12:47 +0100260 using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature));
Marco Poletti36253c92015-07-19 17:12:47 +0100261 using AnnotatedCDeps = ExpandProvidersInParams(NormalizeTypeVector(SignatureArgs(AnnotatedSignature)));
Marco Poletti010daa62015-07-06 01:15:12 +0100262 using R = AddProvidedType(Comp, AnnotatedC, AnnotatedCDeps);
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000263 using type = If(Not(IsSame(Signature, SignatureFromLambda)),
Marco Poletti010daa62015-07-06 01:15:12 +0100264 ConstructError(AnnotatedSignatureDifferentFromLambdaSignatureErrorTag, Signature, SignatureFromLambda),
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000265 ComponentFunctorIdentity(R));
Marco Poletti31f638a2015-05-10 21:21:25 +0100266 };
267};
268
269// The registration is actually deferred until the PartialComponent is converted to a component.
Marco Poletti31f638a2015-05-10 21:21:25 +0100270struct DeferredRegisterProviderWithAnnotations {
Marco Poletti010daa62015-07-06 01:15:12 +0100271 template <typename Comp, typename AnnotatedSignature, typename Lambda>
Marco Poletti31f638a2015-05-10 21:21:25 +0100272 struct apply {
Marco Poletti36253c92015-07-19 17:12:47 +0100273 using Comp1 = AddDeferredBinding(Comp,
274 ComponentFunctor(PostProcessRegisterProvider, AnnotatedSignature, Lambda));
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000275 using type = PreProcessRegisterProvider(Comp1, AnnotatedSignature, Lambda);
Marco Polettie9c143b2015-03-08 16:46:50 +0000276 };
277};
278
Marco Polettid8943a82015-01-01 15:57:16 +0100279// The registration is actually deferred until the PartialComponent is converted to a component.
Marco Polettie4647132015-05-31 14:35:27 +0100280struct DeferredRegisterProvider {
Marco Poletti010daa62015-07-06 01:15:12 +0100281 template <typename Comp, typename Lambda>
Marco Polettie4647132015-05-31 14:35:27 +0100282 struct apply {
Marco Polettiebe12252016-03-26 11:41:40 +0000283 using type = DeferredRegisterProviderWithAnnotations(Comp, FunctionSignature(Lambda), Lambda);
Marco Polettie4647132015-05-31 14:35:27 +0100284 };
285};
Marco Poletti31f638a2015-05-10 21:21:25 +0100286
287// T can't be any injectable type, it must match the return type of the provider in one of
288// the registerMultibindingProvider() overloads in ComponentStorage.
Marco Poletti31f638a2015-05-10 21:21:25 +0100289struct RegisterMultibindingProviderWithAnnotations {
Marco Poletti010daa62015-07-06 01:15:12 +0100290 template <typename Comp, typename AnnotatedSignature, typename Lambda>
Marco Polettid8943a82015-01-01 15:57:16 +0100291 struct apply {
Marco Poletti36253c92015-07-19 17:12:47 +0100292 using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature);
293 using SignatureFromLambda = FunctionSignature(Lambda);
Marco Poletti010daa62015-07-06 01:15:12 +0100294
Marco Poletti36253c92015-07-19 17:12:47 +0100295 using AnnotatedArgs = SignatureArgs(AnnotatedSignature);
296 using AnnotatedArgVector = ExpandProvidersInParams(NormalizeTypeVector(AnnotatedArgs));
297 using R = AddRequirements(Comp, AnnotatedArgVector);
Marco Poletti010daa62015-07-06 01:15:12 +0100298 struct Op {
Marco Poletti3b95a512015-07-11 13:43:39 +0100299 using Result = Eval<R>;
Marco Poletti31f638a2015-05-10 21:21:25 +0100300 void operator()(ComponentStorage& storage) {
Marco Poletti36253c92015-07-19 17:12:47 +0100301 auto multibindingData = InjectorStorage::createMultibindingDataForProvider<
302 UnwrapType<AnnotatedSignature>, UnwrapType<Lambda>>();
303 storage.addMultibinding(multibindingData);
Marco Poletti31f638a2015-05-10 21:21:25 +0100304 }
Marco Polettib9f19bf2015-01-01 17:07:25 +0100305 };
Marco Poletti3c544832015-12-01 22:52:21 +0100306 using type = If(Not(IsValidSignature(AnnotatedSignature)),
307 ConstructError(NotASignatureErrorTag, AnnotatedSignature),
308 If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))),
309 ConstructError(CannotConstructAbstractClassErrorTag, RemoveAnnotations(SignatureType(AnnotatedSignature))),
Marco Poletti010daa62015-07-06 01:15:12 +0100310 If(Not(IsSame(Signature, SignatureFromLambda)),
311 ConstructError(AnnotatedSignatureDifferentFromLambdaSignatureErrorTag, Signature, SignatureFromLambda),
Marco Poletti36253c92015-07-19 17:12:47 +0100312 PropagateError(R,
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000313 Op))));
Marco Polettica50c3a2014-12-31 18:26:52 +0100314 };
Marco Poletti4d39c582014-11-24 18:33:48 +0000315};
316
317// T can't be any injectable type, it must match the return type of the provider in one of
318// the registerMultibindingProvider() overloads in ComponentStorage.
Marco Polettie4647132015-05-31 14:35:27 +0100319struct RegisterMultibindingProvider {
Marco Poletti010daa62015-07-06 01:15:12 +0100320 template <typename Comp, typename Lambda>
Marco Polettie4647132015-05-31 14:35:27 +0100321 struct apply {
Marco Polettiebe12252016-03-26 11:41:40 +0000322 using type = RegisterMultibindingProviderWithAnnotations(Comp, FunctionSignature(Lambda), Lambda);
Marco Polettie4647132015-05-31 14:35:27 +0100323 };
324};
Marco Poletti4d39c582014-11-24 18:33:48 +0000325
326// Non-assisted case.
Marco Poletti905dc092017-03-12 15:54:31 +0000327template <int numAssistedBefore, int numNonAssistedBefore, typename Arg>
Marco Poletti9754d5a2014-11-24 19:46:28 +0000328struct GetAssistedArg {
Marco Poletti905dc092017-03-12 15:54:31 +0000329 template <typename InjectedArgsTuple, typename UserProvidedArgsTuple>
Marco Poletti4d39c582014-11-24 18:33:48 +0000330 inline Arg operator()(InjectedArgsTuple& injected_args, UserProvidedArgsTuple&) {
331 return std::get<numNonAssistedBefore>(injected_args);
332 }
333};
334
335// Assisted case.
Marco Poletti905dc092017-03-12 15:54:31 +0000336template <int numAssistedBefore, int numNonAssistedBefore, typename Arg>
337struct GetAssistedArg<numAssistedBefore, numNonAssistedBefore, Assisted<Arg>> {
338 template <typename InjectedArgsTuple, typename UserProvidedArgsTuple>
339 inline Arg operator()(InjectedArgsTuple&, UserProvidedArgsTuple& user_provided_args) {
Marco Poletti4d39c582014-11-24 18:33:48 +0000340 return std::get<numAssistedBefore>(user_provided_args);
341 }
342};
Marco Poletti36253c92015-07-19 17:12:47 +0100343
Marco Poletti010daa62015-07-06 01:15:12 +0100344struct RegisterFactoryHelper {
345
346 template <typename Comp,
347 typename DecoratedSignature,
348 typename Lambda,
349 // std::function<InjectedSignature> is the injected type (possibly with an Annotation<> wrapping it)
350 typename InjectedSignature,
351 typename RequiredLambdaSignature,
352 typename InjectedAnnotatedArgs,
353 // The types that are injected, unwrapped from any Annotation<>.
354 typename InjectedArgs,
355 typename IndexSequence>
356 struct apply;
357
358 template <typename Comp, typename DecoratedSignature, typename Lambda, typename NakedC,
359 typename... NakedUserProvidedArgs, typename... NakedAllArgs, typename... InjectedAnnotatedArgs,
Marco Poletti905dc092017-03-12 15:54:31 +0000360 typename... NakedInjectedArgs, typename... Indexes>
Marco Poletti010daa62015-07-06 01:15:12 +0100361 struct apply<Comp, DecoratedSignature, Lambda, Type<NakedC(NakedUserProvidedArgs...)>,
362 Type<NakedC(NakedAllArgs...)>, Vector<InjectedAnnotatedArgs...>,
Marco Poletti905dc092017-03-12 15:54:31 +0000363 Vector<Type<NakedInjectedArgs>...>, Vector<Indexes...>> {
Marco Poletti31f638a2015-05-10 21:21:25 +0100364 // Here we call "decorated" the types that might be wrapped in Annotated<> or Assisted<>,
365 // while we call "annotated" the ones that might only be wrapped in Annotated<> (but not Assisted<>).
Marco Poletti010daa62015-07-06 01:15:12 +0100366 using AnnotatedT = SignatureType(DecoratedSignature);
367 using T = RemoveAnnotations(AnnotatedT);
368 using DecoratedArgs = SignatureArgs(DecoratedSignature);
369 using NakedInjectedSignature = NakedC(NakedUserProvidedArgs...);
370 using NakedRequiredSignature = NakedC(NakedAllArgs...);
371 using NakedFunctor = std::function<NakedInjectedSignature>;
Marco Poletti31f638a2015-05-10 21:21:25 +0100372 // This is usually the same as Functor, but this might be annotated.
Marco Poletti010daa62015-07-06 01:15:12 +0100373 using AnnotatedFunctor = CopyAnnotation(AnnotatedT, Type<NakedFunctor>);
374 using FunctorDeps = NormalizeTypeVector(Vector<InjectedAnnotatedArgs...>);
375 using R = AddProvidedType(Comp, AnnotatedFunctor, FunctorDeps);
376 struct Op {
Marco Poletti3b95a512015-07-11 13:43:39 +0100377 using Result = Eval<R>;
Marco Polettib9f19bf2015-01-01 17:07:25 +0100378 void operator()(ComponentStorage& storage) {
Marco Poletti010daa62015-07-06 01:15:12 +0100379 auto function_provider = [](NakedInjectedArgs... args) {
Marco Polettib9f19bf2015-01-01 17:07:25 +0100380 // TODO: Using auto and make_tuple here results in a GCC segfault with GCC 4.8.1.
381 // Check this on later versions and consider filing a bug.
Marco Poletti010daa62015-07-06 01:15:12 +0100382 std::tuple<NakedInjectedArgs...> injected_args(args...);
383 auto object_provider = [injected_args](NakedUserProvidedArgs... params) mutable {
Marco Polettib9f19bf2015-01-01 17:07:25 +0100384 auto user_provided_args = std::tie(params...);
Marco Poletti905dc092017-03-12 15:54:31 +0000385 // These are unused if they are 0-arg tuples. Silence the unused-variable warnings anyway.
386 (void) injected_args;
387 (void) user_provided_args;
388
389 return LambdaInvoker::invoke<UnwrapType<Lambda>, NakedAllArgs...>(
390 GetAssistedArg<
391 Eval<NumAssistedBefore(Indexes, DecoratedArgs)>::value,
392 Indexes::value - Eval<NumAssistedBefore(Indexes, DecoratedArgs)>::value,
393 // Note that the Assisted<> wrapper (if any) remains, we just remove any wrapping Annotated<>.
394 UnwrapType<Eval<RemoveAnnotations(GetNthType(Indexes, DecoratedArgs))>>
395 >()(injected_args, user_provided_args)...);
396 };
Marco Poletti010daa62015-07-06 01:15:12 +0100397 return NakedFunctor(object_provider);
Marco Poletticc97a162015-05-10 12:10:12 +0100398 };
Marco Poletti010daa62015-07-06 01:15:12 +0100399 storage.addBinding(InjectorStorage::createBindingDataForProvider<
Marco Poletti3b95a512015-07-11 13:43:39 +0100400 UnwrapType<Eval<ConsSignatureWithVector(AnnotatedFunctor, Vector<InjectedAnnotatedArgs...>)>>,
Marco Poletti010daa62015-07-06 01:15:12 +0100401 decltype(function_provider)>());
Marco Polettib9f19bf2015-01-01 17:07:25 +0100402 }
403 };
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000404 // The first two IsValidSignature checks are a bit of a hack, they are needed to make the F2/RealF2 split
Marco Polettif41d2362015-12-07 17:03:51 +0000405 // work in the caller (we need to allow Lambda to be a function type).
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000406 using type = If(Not(Or(IsEmpty(Lambda), IsValidSignature(Lambda))),
Marco Poletti010daa62015-07-06 01:15:12 +0100407 ConstructError(LambdaWithCapturesErrorTag, Lambda),
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000408 If(Not(Or(IsTriviallyCopyable(Lambda), IsValidSignature(Lambda))),
Marco Polettif41d2362015-12-07 17:03:51 +0000409 ConstructError(NonTriviallyCopyableLambdaErrorTag, Lambda),
Marco Poletti010daa62015-07-06 01:15:12 +0100410 If(Not(IsSame(Type<NakedRequiredSignature>, FunctionSignature(Lambda))),
411 ConstructError(FunctorSignatureDoesNotMatchErrorTag, Type<NakedRequiredSignature>, FunctionSignature(Lambda)),
412 If(IsPointer(T),
413 ConstructError(FactoryReturningPointerErrorTag, DecoratedSignature),
Marco Poletti36253c92015-07-19 17:12:47 +0100414 PropagateError(R,
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000415 Op)))));
Marco Polettica50c3a2014-12-31 18:26:52 +0100416 };
Marco Poletti4d39c582014-11-24 18:33:48 +0000417};
418
Marco Poletti010daa62015-07-06 01:15:12 +0100419struct RegisterFactory {
420 template <typename Comp, typename DecoratedSignature, typename Lambda>
421 struct apply {
Marco Poletti3c544832015-12-01 22:52:21 +0100422 using type = If(Not(IsValidSignature(DecoratedSignature)),
423 ConstructError(NotASignatureErrorTag, DecoratedSignature),
424 If(IsAbstract(RemoveAnnotations(SignatureType(DecoratedSignature))),
425 // We error out early in this case. Calling RegisterFactoryHelper would also produce an error, but it'd be
426 // much less user-friendly.
427 ConstructError(CannotConstructAbstractClassErrorTag, RemoveAnnotations(SignatureType(DecoratedSignature))),
428 RegisterFactoryHelper(Comp,
Marco Poletti010daa62015-07-06 01:15:12 +0100429 DecoratedSignature,
430 Lambda,
431 InjectedSignatureForAssistedFactory(DecoratedSignature),
432 RequiredLambdaSignatureForAssistedFactory(DecoratedSignature),
433 RemoveAssisted(SignatureArgs(DecoratedSignature)),
434 RemoveAnnotationsFromVector(RemoveAssisted(SignatureArgs(DecoratedSignature))),
Marco Poletti36253c92015-07-19 17:12:47 +0100435 GenerateIntSequence(
Marco Poletti3c544832015-12-01 22:52:21 +0100436 VectorSize(RequiredLambdaArgsForAssistedFactory(DecoratedSignature))))));
Marco Poletti010daa62015-07-06 01:15:12 +0100437 };
438};
439
Marco Polettie9c143b2015-03-08 16:46:50 +0000440struct PostProcessRegisterConstructor;
Marco Poletti4d39c582014-11-24 18:33:48 +0000441
Marco Poletti31f638a2015-05-10 21:21:25 +0100442template <typename AnnotatedSignature, typename OptionalAnnotatedI>
Marco Poletticc97a162015-05-10 12:10:12 +0100443struct PostProcessRegisterConstructorHelper;
444
Marco Poletti31f638a2015-05-10 21:21:25 +0100445template <typename AnnotatedSignature, typename AnnotatedI>
Marco Poletti010daa62015-07-06 01:15:12 +0100446struct PostProcessRegisterConstructorHelper;
447
448template <typename AnnotatedSignature, typename AnnotatedI>
449struct PostProcessRegisterConstructorHelper<AnnotatedSignature, Type<AnnotatedI>> {
Marco Poletti4d39c582014-11-24 18:33:48 +0000450 inline void operator()(ComponentStorage& component) {
Marco Poletti31f638a2015-05-10 21:21:25 +0100451 component.addBinding(InjectorStorage::createBindingDataForConstructor<AnnotatedSignature>());
452 component.addCompressedBinding(InjectorStorage::createBindingDataForCompressedConstructor<AnnotatedSignature, AnnotatedI>());
Marco Poletti4d39c582014-11-24 18:33:48 +0000453 }
454};
455
Marco Poletti31f638a2015-05-10 21:21:25 +0100456template <typename AnnotatedSignature>
457struct PostProcessRegisterConstructorHelper<AnnotatedSignature, None> {
Marco Poletti4d39c582014-11-24 18:33:48 +0000458 inline void operator()(ComponentStorage& component) {
Marco Poletti31f638a2015-05-10 21:21:25 +0100459 component.addBinding(InjectorStorage::createBindingDataForConstructor<AnnotatedSignature>());
Marco Poletti4d39c582014-11-24 18:33:48 +0000460 }
461};
462
Marco Poletti31f638a2015-05-10 21:21:25 +0100463struct PostProcessRegisterConstructor {
Marco Poletti010daa62015-07-06 01:15:12 +0100464 template <typename Comp, typename AnnotatedSignature>
Marco Polettica50c3a2014-12-31 18:26:52 +0100465 struct apply {
Marco Polettib9f19bf2015-01-01 17:07:25 +0100466 struct type {
Marco Poletti010daa62015-07-06 01:15:12 +0100467 using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature));
Marco Polettie9c143b2015-03-08 16:46:50 +0000468 using Result = Comp;
Marco Polettib9f19bf2015-01-01 17:07:25 +0100469 void operator()(ComponentStorage& storage) {
Marco Poletti010daa62015-07-06 01:15:12 +0100470 PostProcessRegisterConstructorHelper<
Marco Poletti3b95a512015-07-11 13:43:39 +0100471 UnwrapType<AnnotatedSignature>,
Marco Poletti1e44d552017-05-20 14:10:38 +0100472 Eval<FindValueInMap(typename Comp::InterfaceBindings, AnnotatedC)>
Marco Poletti010daa62015-07-06 01:15:12 +0100473 >()(storage);
Marco Polettib9f19bf2015-01-01 17:07:25 +0100474 }
475 };
Marco Polettid8943a82015-01-01 15:57:16 +0100476 };
477};
478
Marco Polettie9c143b2015-03-08 16:46:50 +0000479struct PreProcessRegisterConstructor {
Marco Poletti010daa62015-07-06 01:15:12 +0100480 template <typename Comp, typename AnnotatedSignature>
Marco Polettid8943a82015-01-01 15:57:16 +0100481 struct apply {
Marco Poletti010daa62015-07-06 01:15:12 +0100482 using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature);
483 using C = SignatureType(Signature);
484 using Args = SignatureArgs(Signature);
485 using AnnotatedT = SignatureType(AnnotatedSignature);
486 using AnnotatedArgs = SignatureArgs(AnnotatedSignature);
487 using AnnotatedC = NormalizeType(AnnotatedT);
488 using CDeps = ExpandProvidersInParams(NormalizeTypeVector(AnnotatedArgs));
489 using R = AddProvidedType(Comp, AnnotatedC, CDeps);
Marco Poletti3c544832015-12-01 22:52:21 +0100490 using type = If(Not(IsValidSignature(AnnotatedSignature)),
Marco Poletti010daa62015-07-06 01:15:12 +0100491 ConstructError(NotASignatureErrorTag, AnnotatedSignature),
Marco Poletti3c544832015-12-01 22:52:21 +0100492 If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))),
493 ConstructError(CannotConstructAbstractClassErrorTag, RemoveAnnotations(SignatureType(AnnotatedSignature))),
Marco Poletti010daa62015-07-06 01:15:12 +0100494 If(Not(IsConstructibleWithVector(C, Args)),
495 ConstructError(NoConstructorMatchingInjectSignatureErrorTag, C, Signature),
Marco Poletti36253c92015-07-19 17:12:47 +0100496 PropagateError(R,
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000497 ComponentFunctorIdentity(R)))));
Marco Polettie9c143b2015-03-08 16:46:50 +0000498 };
499};
500
Marco Polettie9c143b2015-03-08 16:46:50 +0000501struct DeferredRegisterConstructor {
Marco Poletti010daa62015-07-06 01:15:12 +0100502 template <typename Comp, typename AnnotatedSignature>
Marco Polettie9c143b2015-03-08 16:46:50 +0000503 struct apply {
Marco Poletti010daa62015-07-06 01:15:12 +0100504 using Comp1 = AddDeferredBinding(Comp,
505 ComponentFunctor(PostProcessRegisterConstructor, AnnotatedSignature));
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000506 using type = PreProcessRegisterConstructor(Comp1, AnnotatedSignature);
Marco Poletti4d39c582014-11-24 18:33:48 +0000507 };
508};
509
Marco Polettica50c3a2014-12-31 18:26:52 +0100510struct RegisterInstance {
Marco Poletti0acba692016-12-10 17:44:38 +0000511 template <typename Comp, typename AnnotatedC, typename C>
Marco Polettica50c3a2014-12-31 18:26:52 +0100512 struct apply {
Marco Poletti010daa62015-07-06 01:15:12 +0100513 using R = AddProvidedType(Comp, AnnotatedC, Vector<>);
514 struct Op {
Marco Poletti3b95a512015-07-11 13:43:39 +0100515 using Result = Eval<R>;
Marco Poletticbe3c7a2016-02-07 09:52:02 +0000516 void operator()(ComponentStorage&) {}
Marco Polettica50c3a2014-12-31 18:26:52 +0100517 };
Marco Poletti0acba692016-12-10 17:44:38 +0000518 using type = If(Not(IsSame(C, NormalizeType(C))),
519 ConstructError(NonClassTypeErrorTag, C, NormalizeType(C)),
520 If(Not(IsSame(RemoveAnnotations(AnnotatedC), NormalizeType(RemoveAnnotations(AnnotatedC)))),
521 ConstructError(NonClassTypeErrorTag, RemoveAnnotations(AnnotatedC), NormalizeType(RemoveAnnotations(C))),
522 // The IsSame check is not redundant because IsBaseOf returns false for non-class types (e.g. int).
523 If(Not(Or(IsSame(RemoveAnnotations(AnnotatedC), C),
524 IsBaseOf(RemoveAnnotations(AnnotatedC), C))),
525 ConstructError(TypeMismatchInBindInstanceErrorTag, RemoveAnnotations(AnnotatedC), C),
526 PropagateError(R,
527 Op))));
Marco Polettica50c3a2014-12-31 18:26:52 +0100528 };
529};
530
Marco Poletti010daa62015-07-06 01:15:12 +0100531struct RegisterConstructorAsValueFactory {
532 template<typename Comp,
533 typename DecoratedSignature,
534 typename RequiredSignature =
Marco Poletti3b95a512015-07-11 13:43:39 +0100535 Eval<RequiredLambdaSignatureForAssistedFactory(DecoratedSignature)>>
Marco Poletti010daa62015-07-06 01:15:12 +0100536 struct apply;
537
538 template <typename Comp, typename DecoratedSignature, typename NakedT, typename... NakedArgs>
539 struct apply<Comp, DecoratedSignature, Type<NakedT(NakedArgs...)>> {
540 using RequiredSignature = Type<NakedT(NakedArgs...)>;
541 using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature);
542 struct Op {
Marco Poletti3b95a512015-07-11 13:43:39 +0100543 using Result = Eval<GetResult(Op1)>;
Marco Polettib9f19bf2015-01-01 17:07:25 +0100544 void operator()(ComponentStorage& storage) {
Marco Poletti010daa62015-07-06 01:15:12 +0100545 auto provider = [](NakedArgs... args) {
546 return NakedT(std::forward<NakedArgs>(args)...);
Marco Polettib9f19bf2015-01-01 17:07:25 +0100547 };
Marco Poletti010daa62015-07-06 01:15:12 +0100548 using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>);
549 FruitStaticAssert(IsSame(GetResult(Op1),
550 GetResult(RealOp)));
Marco Poletti3b95a512015-07-11 13:43:39 +0100551 Eval<RealOp>()(storage);
Marco Polettib9f19bf2015-01-01 17:07:25 +0100552 }
Marco Polettica50c3a2014-12-31 18:26:52 +0100553 };
Marco Poletti36253c92015-07-19 17:12:47 +0100554 using type = PropagateError(Op1,
Marco Poletti010daa62015-07-06 01:15:12 +0100555 Op);
Marco Poletti4d39c582014-11-24 18:33:48 +0000556 };
557};
558
Marco Poletti0e7e5152016-05-14 09:20:05 +0100559
560struct RegisterConstructorAsUniquePtrFactory {
561 template<typename Comp,
562 typename DecoratedSignature,
563 typename RequiredSignature =
564 Eval<RequiredLambdaSignatureForAssistedFactory(DecoratedSignature)>>
565 struct apply;
566
567 template <typename Comp, typename DecoratedSignature, typename NakedT, typename... NakedArgs>
568 struct apply<Comp, DecoratedSignature, Type<std::unique_ptr<NakedT>(NakedArgs...)>> {
569 using RequiredSignature = Type<std::unique_ptr<NakedT>(NakedArgs...)>;
570 using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature);
571 struct Op {
572 using Result = Eval<GetResult(Op1)>;
573 void operator()(ComponentStorage& storage) {
574 auto provider = [](NakedArgs... args) {
575 return std::unique_ptr<NakedT>(new NakedT(std::forward<NakedArgs>(args)...));
576 };
577 using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>);
578 FruitStaticAssert(IsSame(GetResult(Op1),
579 GetResult(RealOp)));
580 Eval<RealOp>()(storage);
581 };
582 };
583
584 using type = PropagateError(Op1,
585 Op);
586 };
587};
588
Marco Poletti4d39c582014-11-24 18:33:48 +0000589struct InstallComponent {
Marco Poletti010daa62015-07-06 01:15:12 +0100590 template <typename Comp, typename OtherComp>
Marco Polettica50c3a2014-12-31 18:26:52 +0100591 struct apply {
Marco Poletti36253c92015-07-19 17:12:47 +0100592 using new_RsSuperset = SetUnion(typename OtherComp::RsSuperset,
593 typename Comp::RsSuperset);
Marco Polettiec5c5202015-07-26 11:18:44 +0100594 using new_Ps = SetUncheckedUnion(typename OtherComp::Ps,
595 typename Comp::Ps);
Marco Poletti42c3b7c2016-05-22 09:32:36 +0100596#ifndef FRUIT_NO_LOOP_CHECK
Marco Poletti36253c92015-07-19 17:12:47 +0100597 using new_Deps = ConcatVectors(typename OtherComp::Deps,
598 typename Comp::Deps);
Marco Poletti42c3b7c2016-05-22 09:32:36 +0100599#endif
Marco Poletticd6625f2016-03-26 11:31:08 +0000600 FruitStaticAssert(IsSame(typename OtherComp::InterfaceBindings, Vector<>));
601 using new_InterfaceBindings = typename Comp::InterfaceBindings;
Marco Poletti36253c92015-07-19 17:12:47 +0100602
603 FruitStaticAssert(IsSame(typename OtherComp::DeferredBindingFunctors, EmptyList));
604 using new_DeferredBindingFunctors = typename Comp::DeferredBindingFunctors;
605
Marco Poletti42c3b7c2016-05-22 09:32:36 +0100606 using R = ConsComp(new_RsSuperset, new_Ps,
607#ifndef FRUIT_NO_LOOP_CHECK
608 new_Deps,
609#endif
610 new_InterfaceBindings, new_DeferredBindingFunctors);
Marco Poletti010daa62015-07-06 01:15:12 +0100611 struct Op {
Marco Poletti3b95a512015-07-11 13:43:39 +0100612 using Result = Eval<R>;
Marco Poletticbe3c7a2016-02-07 09:52:02 +0000613 void operator()(ComponentStorage&) {}
Marco Polettib9f19bf2015-01-01 17:07:25 +0100614 };
Marco Poletti417e0452016-11-20 14:23:37 +0000615 using InterfacePs = VectorToSetUnchecked(GetMapKeys(typename Comp::InterfaceBindings));
616 using AllPs = SetUncheckedUnion(InterfacePs, typename Comp::Ps);
Marco Poletti36253c92015-07-19 17:12:47 +0100617 using DuplicateTypes = SetIntersection(typename OtherComp::Ps,
Marco Poletti417e0452016-11-20 14:23:37 +0000618 AllPs);
619 using type = If(Not(IsDisjoint(typename OtherComp::Ps, AllPs)),
Marco Poletti36253c92015-07-19 17:12:47 +0100620 ConstructErrorWithArgVector(DuplicateTypesInComponentErrorTag,
621 SetToVector(DuplicateTypes)),
Marco Poletti010daa62015-07-06 01:15:12 +0100622 Op);
Marco Polettica50c3a2014-12-31 18:26:52 +0100623 };
Marco Poletti4d39c582014-11-24 18:33:48 +0000624};
625
Marco Polettia19fd1e2015-03-07 18:50:37 +0000626struct InstallComponentHelper {
Marco Poletti010daa62015-07-06 01:15:12 +0100627 template <typename Comp, typename... OtherCompParams>
Marco Polettia19fd1e2015-03-07 18:50:37 +0000628 struct apply {
Marco Poletti010daa62015-07-06 01:15:12 +0100629 using OtherComp = ConstructComponentImpl(OtherCompParams...);
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000630 using type = InstallComponent(Comp, OtherComp);
Marco Polettia19fd1e2015-03-07 18:50:37 +0000631 };
Marco Poletti4d39c582014-11-24 18:33:48 +0000632};
633
Marco Poletti4d39c582014-11-24 18:33:48 +0000634struct ConvertComponent {
Marco Poletti010daa62015-07-06 01:15:12 +0100635 template <typename SourceComp, typename DestComp>
Marco Polettica50c3a2014-12-31 18:26:52 +0100636 struct apply {
637 // We need to register:
638 // * All the types provided by the new component
639 // * All the types required by the old component
640 // except:
641 // * The ones already provided by the old component.
642 // * The ones required by the new one.
Marco Poletti36253c92015-07-19 17:12:47 +0100643 using SourcePs = typename SourceComp::Ps;
644 using DestPs = typename DestComp::Ps;
645 using SourceRs = SetDifference(typename SourceComp::RsSuperset, typename SourceComp::Ps);
646 using DestRs = SetDifference(typename DestComp::RsSuperset, typename DestComp::Ps);
647 using ToRegister = SetDifference(SetUnion(DestPs, SourceRs),
648 SetUnion(DestRs, SourcePs));
649 using type = EnsureProvidedTypes(SourceComp, DestRs, SetToVector(ToRegister));
Marco Polettica50c3a2014-12-31 18:26:52 +0100650
651 // Not needed, just double-checking.
652 // Uses FruitStaticAssert instead of FruitDelegateCheck so that it's checked only in debug mode.
Marco Poletti010daa62015-07-06 01:15:12 +0100653#ifdef FRUIT_EXTRA_DEBUG
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000654 FruitDelegateCheck(CheckComponentEntails(GetResult(type), DestComp));
Marco Poletti010daa62015-07-06 01:15:12 +0100655#endif // FRUIT_EXTRA_DEBUG
Marco Polettica50c3a2014-12-31 18:26:52 +0100656 };
Marco Poletti4d39c582014-11-24 18:33:48 +0000657};
658
Marco Polettid8943a82015-01-01 15:57:16 +0100659struct ProcessDeferredBindings {
660 template <typename Comp>
661 struct apply;
662
Marco Poletti42c3b7c2016-05-22 09:32:36 +0100663 template <typename RsSupersetParam, typename PsParam,
664#ifndef FRUIT_NO_LOOP_CHECK
665 typename DepsParam,
666#endif
667 typename InterfaceBindingsParam, typename DeferredBindingFunctors>
668 struct apply<Comp<RsSupersetParam, PsParam,
669#ifndef FRUIT_NO_LOOP_CHECK
670 DepsParam,
671#endif
672 InterfaceBindingsParam, DeferredBindingFunctors>> {
Marco Polettid8943a82015-01-01 15:57:16 +0100673 // Comp1 is the same as Comp, but without the DeferredBindingFunctors.
Marco Poletti42c3b7c2016-05-22 09:32:36 +0100674 using Comp1 = ConsComp(RsSupersetParam, PsParam,
675#ifndef FRUIT_NO_LOOP_CHECK
676 DepsParam,
677#endif
678 InterfaceBindingsParam, EmptyList);
Marco Poletti36253c92015-07-19 17:12:47 +0100679 using type = Call(FoldList(DeferredBindingFunctors, Compose2ComponentFunctors, ComponentFunctorIdentity),
680 Comp1);
Marco Polettid8943a82015-01-01 15:57:16 +0100681 };
682};
683
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000684template <typename AnnotatedCFunctor, typename AnnotatedCUniquePtrFunctor>
685struct AutoRegisterFactoryHelperErrorHandler {
686 template <typename E>
687 struct apply {
688 using type = E;
689 };
Marco Poletti66918a42017-01-01 11:17:57 +0100690
691 template <typename T>
692 struct apply<Error<NoBindingFoundErrorTag, T>> {
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000693 using type = If(IsSame(Type<T>, AnnotatedCFunctor),
Marco Poletti66918a42017-01-01 11:17:57 +0100694 ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor),
695 ConstructError(NoBindingFoundErrorTag, Type<T>));
696 };
697
698 template <typename T1, typename T2>
699 struct apply<Error<NoBindingFoundForAbstractClassErrorTag, T1, T2>> {
700 using type = If(IsSame(Type<T1>, AnnotatedCFunctor),
701 ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor),
702 ConstructError(NoBindingFoundForAbstractClassErrorTag, Type<T1>, Type<T2>));
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000703 };
704};
705
Marco Polettie4647132015-05-31 14:35:27 +0100706struct AutoRegisterFactoryHelper {
Marco Poletti010daa62015-07-06 01:15:12 +0100707
708 // General case, no way to bind it.
Marco Poletti36253c92015-07-19 17:12:47 +0100709 template <typename Comp, typename TargetRequirements, typename InterfaceBinding,
Marco Poletti010daa62015-07-06 01:15:12 +0100710 typename has_inject_annotation, typename is_abstract, typename C,
711 typename AnnotatedSignature, typename... Args>
Marco Polettie4647132015-05-31 14:35:27 +0100712 struct apply {
Marco Poletti010daa62015-07-06 01:15:12 +0100713 using AnnotatedC = SignatureType(AnnotatedSignature);
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000714 using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature));
Marco Poletti010daa62015-07-06 01:15:12 +0100715 using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor);
Marco Poletti3c544832015-12-01 22:52:21 +0100716 using type = If(IsAbstract(C),
Marco Poletti66918a42017-01-01 11:17:57 +0100717 ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, C),
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000718 ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor));
Marco Polettie4647132015-05-31 14:35:27 +0100719 };
Marco Polettie4647132015-05-31 14:35:27 +0100720
Marco Poletti36253c92015-07-19 17:12:47 +0100721 // No way to bind it (we need this specialization too to ensure that the specialization below
Marco Poletti09547542015-07-25 12:13:24 +0100722 // is not chosen for AnnotatedC=None).
Marco Poletti010daa62015-07-06 01:15:12 +0100723 template <typename Comp, typename TargetRequirements, typename unused1, typename unused2,
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000724 typename NakedI, typename AnnotatedSignature, typename... Args>
Marco Poletti36253c92015-07-19 17:12:47 +0100725 struct apply<Comp, TargetRequirements, None, unused1, unused2, Type<std::unique_ptr<NakedI>>,
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000726 AnnotatedSignature, Args...> {
Marco Poletti36253c92015-07-19 17:12:47 +0100727 using AnnotatedC = SignatureType(AnnotatedSignature);
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000728 using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature));
Marco Poletti36253c92015-07-19 17:12:47 +0100729 using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor);
Marco Poletti3c544832015-12-01 22:52:21 +0100730 using type = If(IsAbstract(Type<NakedI>),
Marco Poletti66918a42017-01-01 11:17:57 +0100731 ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, Type<NakedI>),
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000732 ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor));
Marco Poletti36253c92015-07-19 17:12:47 +0100733 };
734
735 // AnnotatedI has an interface binding, use it and look for a factory that returns the type that AnnotatedI is bound to.
736 template <typename Comp, typename TargetRequirements, typename AnnotatedC, typename unused1, typename unused2,
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000737 typename NakedI, typename AnnotatedSignature, typename... Args>
Marco Poletti36253c92015-07-19 17:12:47 +0100738 struct apply<Comp, TargetRequirements, AnnotatedC, unused1, unused2, Type<std::unique_ptr<NakedI>>,
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000739 AnnotatedSignature, Args...> {
Marco Poletti010daa62015-07-06 01:15:12 +0100740 using I = Type<NakedI>;
741 using AnnotatedI = CopyAnnotation(SignatureType(AnnotatedSignature), I);
Marco Poletti010daa62015-07-06 01:15:12 +0100742 using C = RemoveAnnotations(AnnotatedC);
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000743 using IFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(I), Args...));
744 using CFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...));
Marco Poletti010daa62015-07-06 01:15:12 +0100745 using AnnotatedIFunctor = CopyAnnotation(AnnotatedI, IFunctor);
746 using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor);
747
748 using ProvidedSignature = ConsSignature(AnnotatedIFunctor, CopyAnnotation(AnnotatedC, ConsReference(CFunctor)));
749 using LambdaSignature = ConsSignature(IFunctor, ConsReference(CFunctor));
750
751 using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, AnnotatedCFunctor);
752 using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature);
753 using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature);
Marco Poletti36253c92015-07-19 17:12:47 +0100754 using R = Call(ComposeFunctors(F1, F2, F3), Comp);
Marco Poletti010daa62015-07-06 01:15:12 +0100755 struct Op {
Marco Poletti36253c92015-07-19 17:12:47 +0100756 using Result = Eval<GetResult(R)>;
Marco Poletti010daa62015-07-06 01:15:12 +0100757 void operator()(ComponentStorage& storage) {
Marco Poletti3b95a512015-07-11 13:43:39 +0100758 using NakedC = UnwrapType<Eval<C>>;
759 auto provider = [](UnwrapType<Eval<CFunctor>>& fun) {
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000760 return UnwrapType<Eval<IFunctor>>([=](UnwrapType<Args>... args) {
Marco Poletti010daa62015-07-06 01:15:12 +0100761 NakedC* c = fun(args...).release();
762 NakedI* i = static_cast<NakedI*>(c);
763 return std::unique_ptr<NakedI>(i);
764 });
765 };
766 using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
767 using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
768 using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp);
Marco Poletti36253c92015-07-19 17:12:47 +0100769 FruitStaticAssert(IsSame(GetResult(RealOp), GetResult(R)));
Marco Poletti3b95a512015-07-11 13:43:39 +0100770 Eval<RealOp>()(storage);
Marco Poletti010daa62015-07-06 01:15:12 +0100771 }
772 };
Marco Poletti36253c92015-07-19 17:12:47 +0100773 using type = PropagateError(R,
Marco Poletti010daa62015-07-06 01:15:12 +0100774 Op);
775 };
776
777 // C doesn't have an interface binding as interface, nor an INJECT annotation, and is not an abstract class.
778 // Bind std::function<unique_ptr<C>(Args...)> to std::function<C(Args...)> (possibly with annotations).
779 template <typename Comp, typename TargetRequirements, typename NakedC, typename AnnotatedSignature,
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000780 typename... Args>
Marco Poletti36253c92015-07-19 17:12:47 +0100781 struct apply<Comp, TargetRequirements, None, Bool<false>, Bool<false>,
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000782 Type<std::unique_ptr<NakedC>>, AnnotatedSignature, Args...> {
Marco Poletti010daa62015-07-06 01:15:12 +0100783 using C = Type<NakedC>;
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000784 using CFunctor = ConsStdFunction(ConsSignature(C, Args...));
785 using CUniquePtrFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...));
Marco Poletti010daa62015-07-06 01:15:12 +0100786 using AnnotatedCUniquePtr = SignatureType(AnnotatedSignature);
787 using AnnotatedC = CopyAnnotation(AnnotatedCUniquePtr, C);
788 using AnnotatedCFunctor = CopyAnnotation(AnnotatedCUniquePtr, CFunctor);
789 using AnnotatedCUniquePtrFunctor = CopyAnnotation(AnnotatedCUniquePtr, CUniquePtrFunctor);
790 using AnnotatedCFunctorRef = CopyAnnotation(AnnotatedCUniquePtr, ConsReference(CFunctor));
Marco Polettica50c3a2014-12-31 18:26:52 +0100791
Marco Poletti010daa62015-07-06 01:15:12 +0100792 using ProvidedSignature = ConsSignature(AnnotatedCUniquePtrFunctor, AnnotatedCFunctorRef);
793 using LambdaSignature = ConsSignature(CUniquePtrFunctor, ConsReference(CFunctor));
794
795 using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, AnnotatedCFunctor);
796 using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature);
797 using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature);
Marco Poletti36253c92015-07-19 17:12:47 +0100798 using R = Call(ComposeFunctors(F1, F2, F3), Comp);
Marco Poletti010daa62015-07-06 01:15:12 +0100799 struct Op {
Marco Poletti36253c92015-07-19 17:12:47 +0100800 using Result = Eval<GetResult(R)>;
Marco Polettib9f19bf2015-01-01 17:07:25 +0100801 void operator()(ComponentStorage& storage) {
Marco Poletti3b95a512015-07-11 13:43:39 +0100802 auto provider = [](UnwrapType<Eval<CFunctor>>& fun) {
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000803 return UnwrapType<Eval<CUniquePtrFunctor>>([=](UnwrapType<Args>... args) {
Marco Poletti010daa62015-07-06 01:15:12 +0100804 NakedC* c = new NakedC(fun(args...));
805 return std::unique_ptr<NakedC>(c);
Marco Polettib9f19bf2015-01-01 17:07:25 +0100806 });
807 };
Marco Poletti010daa62015-07-06 01:15:12 +0100808 using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
809 using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
810 using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp);
Marco Poletti36253c92015-07-19 17:12:47 +0100811 FruitStaticAssert(IsSame(GetResult(RealOp), GetResult(R)));
Marco Poletti3b95a512015-07-11 13:43:39 +0100812 Eval<RealOp>()(storage);
Marco Polettib9f19bf2015-01-01 17:07:25 +0100813 }
814 };
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000815
816 using ErrorHandler = AutoRegisterFactoryHelperErrorHandler<Eval<AnnotatedCFunctor>, Eval<AnnotatedCUniquePtrFunctor>>;
817
818 // If we are about to report a NoBindingFound/NoBindingFoundForAbstractClass error for AnnotatedCFunctor,
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000819 // report one for std::function<std::unique_ptr<C>(Args...)> instead,
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000820 // otherwise we'd report an error about a type that the user doesn't expect.
821 using type = PropagateError(Catch(Catch(R,
822 NoBindingFoundErrorTag, ErrorHandler),
823 NoBindingFoundForAbstractClassErrorTag, ErrorHandler),
824 Op);
Marco Polettica50c3a2014-12-31 18:26:52 +0100825 };
Marco Poletti4d39c582014-11-24 18:33:48 +0000826
Marco Poletti0e7e5152016-05-14 09:20:05 +0100827 // C has an Inject typedef, use it. unique_ptr case.
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000828 template <typename Comp, typename TargetRequirements, typename unused, typename NakedC, typename AnnotatedSignature, typename... Args>
829 struct apply<Comp, TargetRequirements, None, Bool<true>, unused, Type<std::unique_ptr<NakedC>>, AnnotatedSignature, Args...> {
Marco Poletti0e7e5152016-05-14 09:20:05 +0100830 using AnnotatedCUniquePtr = SignatureType(AnnotatedSignature);
831 using AnnotatedC = CopyAnnotation(AnnotatedCUniquePtr, RemoveUniquePtr(RemoveAnnotations(AnnotatedCUniquePtr)));
832 using DecoratedSignatureReturningValue = GetInjectAnnotation(AnnotatedC);
833 using DecoratedSignature = ConsSignatureWithVector(AnnotatedCUniquePtr,
834 SignatureArgs(DecoratedSignatureReturningValue));
835 using DecoratedSignatureArgs = SignatureArgs(DecoratedSignature);
836 using ActualSignatureInInjectionTypedef = ConsSignatureWithVector(SignatureType(DecoratedSignature),
837 RemoveNonAssisted(DecoratedSignatureArgs));
838 using NonAssistedArgs = RemoveAssisted(DecoratedSignatureArgs);
839
840 using F1 = ComponentFunctor(RegisterConstructorAsUniquePtrFactory, DecoratedSignature);
841 using F2 = ComponentFunctor(EnsureProvidedTypes, TargetRequirements, ExpandProvidersInParams(NonAssistedArgs));
842
843 using type = If(Not(IsSame(AnnotatedSignature, ActualSignatureInInjectionTypedef)),
844 ConstructError(FunctorSignatureDoesNotMatchErrorTag, AnnotatedSignature, ActualSignatureInInjectionTypedef),
845 Call(ComposeFunctors(F1, F2), Comp));
Marco Poletti36253c92015-07-19 17:12:47 +0100846 };
Marco Poletti010daa62015-07-06 01:15:12 +0100847
848 // C has an Inject typedef, use it. Value (not unique_ptr) case.
Marco Polettif8cb4bc2016-03-26 11:45:59 +0000849 template <typename Comp, typename TargetRequirements, typename unused, typename NakedC, typename AnnotatedSignature, typename... Args>
850 struct apply<Comp, TargetRequirements, None, Bool<true>, unused, Type<NakedC>, AnnotatedSignature, Args...> {
Marco Poletti010daa62015-07-06 01:15:12 +0100851 using AnnotatedC = SignatureType(AnnotatedSignature);
852 using DecoratedSignature = GetInjectAnnotation(AnnotatedC);
Marco Poletti36253c92015-07-19 17:12:47 +0100853 using DecoratedSignatureArgs = SignatureArgs(DecoratedSignature);
854 using ActualSignatureInInjectionTypedef = ConsSignatureWithVector(SignatureType(DecoratedSignature),
855 RemoveNonAssisted(DecoratedSignatureArgs));
856 using NonAssistedArgs = RemoveAssisted(DecoratedSignatureArgs);
Marco Polettib9f19bf2015-01-01 17:07:25 +0100857
Marco Poletti010daa62015-07-06 01:15:12 +0100858 using F1 = ComponentFunctor(RegisterConstructorAsValueFactory, DecoratedSignature);
Marco Poletti36253c92015-07-19 17:12:47 +0100859 using F2 = ComponentFunctor(EnsureProvidedTypes, TargetRequirements, ExpandProvidersInParams(NonAssistedArgs));
Marco Poletti010daa62015-07-06 01:15:12 +0100860
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000861 using type = If(Not(IsSame(AnnotatedSignature, ActualSignatureInInjectionTypedef)),
Marco Poletti010daa62015-07-06 01:15:12 +0100862 ConstructError(FunctorSignatureDoesNotMatchErrorTag, AnnotatedSignature, ActualSignatureInInjectionTypedef),
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000863 Call(ComposeFunctors(F1, F2), Comp));
Marco Polettica50c3a2014-12-31 18:26:52 +0100864 };
Marco Poletti4d39c582014-11-24 18:33:48 +0000865};
866
Marco Poletti010daa62015-07-06 01:15:12 +0100867struct AutoRegisterHelper {
868
869 template <typename Comp, typename TargetRequirements, typename has_inject_annotation, typename AnnotatedC>
Marco Polettida1bc0c2015-02-15 13:42:46 +0000870 struct apply;
Marco Poletti4d39c582014-11-24 18:33:48 +0000871
Marco Poletti010daa62015-07-06 01:15:12 +0100872 // C has an Inject typedef, use it.
873 template <typename Comp, typename TargetRequirements, typename AnnotatedC>
874 struct apply<Comp, TargetRequirements, Bool<true>, AnnotatedC> {
875 using Inject = GetInjectAnnotation(AnnotatedC);
Marco Poletti36253c92015-07-19 17:12:47 +0100876 using CRequirements = ExpandProvidersInParams(SignatureArgs(Inject));
Marco Poletti010daa62015-07-06 01:15:12 +0100877 using F = ComposeFunctors(
878 ComponentFunctor(PreProcessRegisterConstructor, Inject),
879 ComponentFunctor(PostProcessRegisterConstructor, Inject),
880 ComponentFunctor(EnsureProvidedTypes, TargetRequirements, CRequirements));
Marco Poletti7e8b15a2015-12-07 22:54:38 +0000881 using type = Call(F, Comp);
Marco Poletti010daa62015-07-06 01:15:12 +0100882 };
883
884
885 template <typename Comp, typename TargetRequirements, typename AnnotatedC>
886 struct apply<Comp, TargetRequirements, Bool<false>, AnnotatedC> {
Marco Poletti66918a42017-01-01 11:17:57 +0100887 using type = ConstructNoBindingFoundError(AnnotatedC);
Marco Polettib9f19bf2015-01-01 17:07:25 +0100888 };
Marco Poletti4d39c582014-11-24 18:33:48 +0000889};
890
Marco Polettie4647132015-05-31 14:35:27 +0100891struct AutoRegister {
Marco Poletti010daa62015-07-06 01:15:12 +0100892 // The types in TargetRequirements will not be auto-registered.
893 template <typename Comp, typename TargetRequirements, typename AnnotatedC>
894 struct apply;
895
896 // Tries to register C by looking for a typedef called Inject inside C.
897 template <typename Comp, typename TargetRequirements, typename AnnotatedC>
Marco Polettie4647132015-05-31 14:35:27 +0100898 struct apply {
Marco Poletti010daa62015-07-06 01:15:12 +0100899 using type = AutoRegisterHelper(Comp,
900 TargetRequirements,
901 HasInjectAnnotation(RemoveAnnotations(AnnotatedC)),
902 AnnotatedC);
903 };
904
905 template <typename Comp, typename TargetRequirements, typename NakedC, typename... NakedArgs>
906 struct apply<Comp, TargetRequirements, Type<std::function<NakedC(NakedArgs...)>>> {
907 using type = AutoRegisterFactoryHelper(Comp,
908 TargetRequirements,
Marco Poletti36253c92015-07-19 17:12:47 +0100909 FindInMap(typename Comp::InterfaceBindings, Type<NakedC>),
Marco Poletti010daa62015-07-06 01:15:12 +0100910 HasInjectAnnotation(Type<NakedC>),
911 IsAbstract(Type<NakedC>),
912 Type<NakedC>,
913 Type<NakedC(NakedArgs...)>,
914 Id<RemoveAnnotations(Type<NakedArgs>)>...);
915 };
916
917 template <typename Comp, typename TargetRequirements, typename NakedC, typename... NakedArgs>
918 struct apply<Comp, TargetRequirements, Type<std::function<std::unique_ptr<NakedC>(NakedArgs...)>>> {
919 using type = AutoRegisterFactoryHelper(Comp,
920 TargetRequirements,
Marco Poletti36253c92015-07-19 17:12:47 +0100921 FindInMap(typename Comp::InterfaceBindings, Type<NakedC>),
Marco Poletti0e7e5152016-05-14 09:20:05 +0100922 HasInjectAnnotation(Type<NakedC>),
Marco Poletti010daa62015-07-06 01:15:12 +0100923 IsAbstract(Type<NakedC>),
924 Type<std::unique_ptr<NakedC>>,
925 Type<std::unique_ptr<NakedC>(NakedArgs...)>,
926 Id<RemoveAnnotations(Type<NakedArgs>)>...);
927 };
928
929 template <typename Comp, typename TargetRequirements, typename Annotation, typename NakedC, typename... NakedArgs>
930 struct apply<Comp, TargetRequirements,
931 Type<fruit::Annotated<Annotation, std::function<NakedC(NakedArgs...)>>>> {
932 using type = AutoRegisterFactoryHelper(Comp,
933 TargetRequirements,
Marco Poletti36253c92015-07-19 17:12:47 +0100934 FindInMap(typename Comp::InterfaceBindings,
935 Type<fruit::Annotated<Annotation, NakedC>>),
Marco Poletti010daa62015-07-06 01:15:12 +0100936 HasInjectAnnotation(Type<NakedC>),
937 IsAbstract(Type<NakedC>),
938 Type<NakedC>,
939 Type<fruit::Annotated<Annotation, NakedC>(NakedArgs...)>,
940 Id<RemoveAnnotations(Type<NakedArgs>)>...);
941 };
942
943 template <typename Comp, typename TargetRequirements, typename Annotation, typename NakedC, typename... NakedArgs>
944 struct apply<Comp, TargetRequirements,
945 Type<fruit::Annotated<Annotation, std::function<std::unique_ptr<NakedC>(NakedArgs...)>>>> {
946 using type = AutoRegisterFactoryHelper(Comp,
947 TargetRequirements,
Marco Poletti36253c92015-07-19 17:12:47 +0100948 FindInMap(typename Comp::InterfaceBindings,
949 Type<fruit::Annotated<Annotation, NakedC>>),
Marco Poletti0e7e5152016-05-14 09:20:05 +0100950 HasInjectAnnotation(Type<NakedC>),
Marco Poletti010daa62015-07-06 01:15:12 +0100951 IsAbstract(Type<NakedC>),
952 Type<std::unique_ptr<NakedC>>,
953 Type<fruit::Annotated<Annotation, std::unique_ptr<NakedC>>(NakedArgs...)>,
954 Id<RemoveAnnotations(Type<NakedArgs>)>...);
Marco Polettie4647132015-05-31 14:35:27 +0100955 };
956};
Marco Poletti4d39c582014-11-24 18:33:48 +0000957
Marco Poletti010daa62015-07-06 01:15:12 +0100958struct EnsureProvidedTypeHelper {
959 template <typename Comp, typename TargetRequirements,
Marco Poletti36253c92015-07-19 17:12:47 +0100960 typename is_already_provided_or_in_target_requirements, typename InterfaceBinding,
Marco Poletti010daa62015-07-06 01:15:12 +0100961 typename AnnotatedC>
962 struct apply;
Marco Poletti4d39c582014-11-24 18:33:48 +0000963
Marco Poletti010daa62015-07-06 01:15:12 +0100964 // Already provided or in target requirements, ok.
965 template <typename Comp, typename TargetRequirements, typename unused, typename AnnotatedC>
966 struct apply<Comp, TargetRequirements, Bool<true>, unused, AnnotatedC> {
Marco Poletti36253c92015-07-19 17:12:47 +0100967 using type = ComponentFunctorIdentity(Comp);
Marco Poletti010daa62015-07-06 01:15:12 +0100968 };
969
970 // Has an interface binding.
Marco Poletti36253c92015-07-19 17:12:47 +0100971 template <typename Comp, typename TargetRequirements, typename AnnotatedC,
972 typename AnnotatedI>
973 struct apply<Comp, TargetRequirements, Bool<false>, AnnotatedC, AnnotatedI> {
Marco Poletti010daa62015-07-06 01:15:12 +0100974 using F1 = ComponentFunctor(ProcessInterfaceBinding, AnnotatedI, AnnotatedC);
975 using F2 = ComponentFunctor(EnsureProvidedType, TargetRequirements, AnnotatedC);
976 using type = Call(ComposeFunctors(F1, F2), Comp);
977 };
978
979 // Not yet provided, nor in target requirements, nor in InterfaceBindings. Try auto-registering.
980 template <typename Comp, typename TargetRequirements, typename AnnotatedC>
Marco Poletti36253c92015-07-19 17:12:47 +0100981 struct apply<Comp, TargetRequirements, Bool<false>, None, AnnotatedC> {
Marco Poletti010daa62015-07-06 01:15:12 +0100982 using type = AutoRegister(Comp, TargetRequirements, AnnotatedC);
Marco Polettib9f19bf2015-01-01 17:07:25 +0100983 };
Marco Polettica50c3a2014-12-31 18:26:52 +0100984};
Marco Poletti4d39c582014-11-24 18:33:48 +0000985
Marco Polettica50c3a2014-12-31 18:26:52 +0100986struct EnsureProvidedType {
Marco Poletti010daa62015-07-06 01:15:12 +0100987 template <typename Comp, typename TargetRequirements, typename AnnotatedT>
Marco Polettib9f19bf2015-01-01 17:07:25 +0100988 struct apply {
Marco Poletti010daa62015-07-06 01:15:12 +0100989 using AnnotatedC = NormalizeType(AnnotatedT);
990 using type = EnsureProvidedTypeHelper(Comp,
991 TargetRequirements,
Marco Polettie5c936b2015-07-25 11:24:27 +0100992 Or(IsInSet(AnnotatedC, typename Comp::Ps),
Marco Poletti36253c92015-07-19 17:12:47 +0100993 IsInSet(AnnotatedC, TargetRequirements)),
994 FindInMap(typename Comp::InterfaceBindings, AnnotatedC),
Marco Poletti010daa62015-07-06 01:15:12 +0100995 AnnotatedC);
Marco Polettib9f19bf2015-01-01 17:07:25 +0100996 };
Marco Polettica50c3a2014-12-31 18:26:52 +0100997};
Marco Poletti4d39c582014-11-24 18:33:48 +0000998
Marco Poletti010daa62015-07-06 01:15:12 +0100999struct EnsureProvidedTypes {
Marco Poletti36253c92015-07-19 17:12:47 +01001000 template <typename Comp, typename TargetRequirements, typename TypeVector>
Marco Polettie4647132015-05-31 14:35:27 +01001001 struct apply {
Marco Poletti36253c92015-07-19 17:12:47 +01001002 struct Helper {
1003 template <typename CurrentResult, typename T>
1004 struct apply {
1005 using type = Compose2ComponentFunctors(ComponentFunctor(EnsureProvidedType, TargetRequirements, T),
1006 CurrentResult);
1007 };
1008 };
1009
1010 using type = Call(FoldVector(TypeVector, Helper, ComponentFunctorIdentity),
1011 Comp);
Marco Polettib9f19bf2015-01-01 17:07:25 +01001012 };
Marco Poletti4d39c582014-11-24 18:33:48 +00001013};
1014
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001015struct ProcessBinding {
1016 template <typename Binding>
1017 struct apply;
1018
1019 template <typename I, typename C>
Marco Poletti0109baa2016-03-25 13:04:47 +00001020 struct apply<fruit::impl::Bind<I, C>> {
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001021 using type = ComponentFunctor(AddDeferredInterfaceBinding, Type<I>, Type<C>);
1022 };
1023
1024 template <typename Signature>
Marco Poletti0109baa2016-03-25 13:04:47 +00001025 struct apply<fruit::impl::RegisterConstructor<Signature>> {
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001026 using type = ComponentFunctor(DeferredRegisterConstructor, Type<Signature>);
1027 };
1028
Marco Poletti0acba692016-12-10 17:44:38 +00001029 template <typename AnnotatedC, typename C>
1030 struct apply<fruit::impl::BindInstance<AnnotatedC, C>> {
1031 using type = ComponentFunctor(RegisterInstance, Type<AnnotatedC>, Type<C>);
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001032 };
1033
1034 template <typename Lambda>
Marco Poletti0109baa2016-03-25 13:04:47 +00001035 struct apply<fruit::impl::RegisterProvider<Lambda>> {
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001036 using type = ComponentFunctor(DeferredRegisterProvider, Type<Lambda>);
1037 };
1038
1039 template <typename AnnotatedSignature, typename Lambda>
Marco Poletti0109baa2016-03-25 13:04:47 +00001040 struct apply<fruit::impl::RegisterProvider<AnnotatedSignature, Lambda>> {
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001041 using type = ComponentFunctor(DeferredRegisterProviderWithAnnotations, Type<AnnotatedSignature>, Type<Lambda>);
1042 };
1043
Marco Poletti0316a002016-08-29 16:43:10 +01001044 template <typename AnnotatedC>
1045 struct apply<fruit::impl::AddInstanceMultibinding<AnnotatedC>> {
1046 using type = ComponentFunctorIdentity;
1047 };
1048
1049 template <typename AnnotatedC>
1050 struct apply<fruit::impl::AddInstanceVectorMultibindings<AnnotatedC>> {
1051 using type = ComponentFunctorIdentity;
1052 };
1053
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001054 template <typename I, typename C>
Marco Poletti0109baa2016-03-25 13:04:47 +00001055 struct apply<fruit::impl::AddMultibinding<I, C>> {
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001056 using type = ComponentFunctor(AddInterfaceMultibinding, Type<I>, Type<C>);
1057 };
1058
1059 template <typename Lambda>
Marco Poletti0109baa2016-03-25 13:04:47 +00001060 struct apply<fruit::impl::AddMultibindingProvider<Lambda>> {
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001061 using type = ComponentFunctor(RegisterMultibindingProvider, Type<Lambda>);
1062 };
1063
1064 template <typename AnnotatedSignature, typename Lambda>
Marco Poletti0109baa2016-03-25 13:04:47 +00001065 struct apply<fruit::impl::AddMultibindingProvider<AnnotatedSignature, Lambda>> {
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001066 using type = ComponentFunctor(RegisterMultibindingProviderWithAnnotations, Type<AnnotatedSignature>, Type<Lambda>);
1067 };
1068
1069 template <typename DecoratedSignature, typename Lambda>
Marco Poletti0109baa2016-03-25 13:04:47 +00001070 struct apply<fruit::impl::RegisterFactory<DecoratedSignature, Lambda>> {
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001071 using type = ComponentFunctor(RegisterFactory, Type<DecoratedSignature>, Type<Lambda>);
1072 };
1073
1074 template <typename... Params>
Marco Poletti0109baa2016-03-25 13:04:47 +00001075 struct apply<fruit::impl::InstallComponent<fruit::Component<Params...>>> {
Marco Poletticbe3c7a2016-02-07 09:52:02 +00001076 using type = ComponentFunctor(InstallComponentHelper, Type<Params>...);
1077 };
1078};
1079
Marco Polettia19fd1e2015-03-07 18:50:37 +00001080} // namespace meta
Marco Poletti4d39c582014-11-24 18:33:48 +00001081} // namespace impl
1082} // namespace fruit
1083
1084
1085#endif // FRUIT_COMPONENT_FUNCTORS_DEFN_H