• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
20 #include <fruit/component.h>
21 
22 #include <fruit/impl/injection_debug_errors.h>
23 #include <fruit/impl/injection_errors.h>
24 #include <fruit/impl/injector/injector_storage.h>
25 
26 #include <memory>
27 
28 /*********************************************************************************************************************************
29   This file contains functors that take a Comp and return a struct Op with the form:
30   struct {
31     using Result = Comp1;
32     void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {...}
33     std::size_t numEntries() {...}
34   }
35 *********************************************************************************************************************************/
36 
37 namespace fruit {
38 namespace impl {
39 namespace meta {
40 
41 struct GetResult {
42   template <typename F>
43   struct apply {
44     using type = typename F::Result;
45   };
46 };
47 
48 // Call(ComponentFunctor(F, Args...), Comp)
49 // is equivalent to:
50 // F(Comp, Args...)
51 struct 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 
63 struct ComponentFunctorIdentity {
64   template <typename Comp>
65   struct apply {
66     struct type {
67       using Result = Comp;
operatorComponentFunctorIdentity::apply::type68       void operator()(FixedSizeVector<ComponentStorageEntry>&) {}
numEntriesComponentFunctorIdentity::apply::type69       std::size_t numEntries() {
70         return 0;
71       }
72     };
73   };
74 };
75 
76 struct Compose2ComponentFunctors {
77   template <typename F1, typename F2>
78   struct apply {
79     struct type {
80       template <typename Comp>
81       struct apply {
82         using Op1 = F1(Comp);
83         using Op2 = F2(GetResult(Op1));
84         struct Op {
85           using Result = Eval<GetResult(Op2)>;
operatorCompose2ComponentFunctors::apply::type::apply::Op86           void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
87             Eval<Op2>()(entries);
88             Eval<Op1>()(entries);
89           }
numEntriesCompose2ComponentFunctors::apply::type::apply::Op90           std::size_t numEntries() {
91             return Eval<Op1>().numEntries() + Eval<Op2>().numEntries();
92           }
93         };
94         using type = PropagateError(Op1, PropagateError(Op2, Op));
95       };
96     };
97   };
98 };
99 
100 // ComposeFunctors(F1,..,Fn) returns a functor that executes F1,..,Fn in order (stopping at the
101 // first Error).
102 struct ComposeFunctors {
103   template <typename... Functors>
104   struct apply {
105     using type = Fold(Compose2ComponentFunctors, ComponentFunctorIdentity, Functors...);
106   };
107 };
108 
109 // ReverseComposeFunctors(T1, ..., Tn) is equivalent to ComposeFunctors(Tn, ..., T1), but it's more
110 // efficient when all of the following must be evaluated:
111 // ReverseComposeFunctors<T1>
112 // ReverseComposeFunctors<T2, T1>
113 // ReverseComposeFunctors<T3, T2, T1>
114 // In that case, this implementation shares many more instantiations with previous invocations
115 struct ReverseComposeFunctors {
116   template <typename... Functors>
117   struct apply {
118     using type = ComponentFunctorIdentity;
119   };
120 
121   template <typename Functor>
122   struct apply<Functor> {
123     using type = Functor;
124   };
125 
126   template <typename Functor, typename... Functors>
127   struct apply<Functor, Functors...> {
128     using type = Compose2ComponentFunctors(ReverseComposeFunctors(Functors...), Functor);
129   };
130 };
131 
132 struct EnsureProvidedType;
133 
134 struct EnsureProvidedTypes;
135 
136 // Doesn't actually bind in ComponentStorage. The binding is added later (if needed) using ProcessInterfaceBinding.
137 struct AddDeferredInterfaceBinding {
138   template <typename Comp, typename AnnotatedI, typename AnnotatedC>
139   struct apply {
140     using Comp1 = ConsComp(typename Comp::RsSuperset, typename Comp::Ps, typename Comp::NonConstRsPs,
141 #if !FRUIT_NO_LOOP_CHECK
142                            typename Comp::Deps,
143 #endif
144                            PushFront(typename Comp::InterfaceBindings, Pair<AnnotatedI, AnnotatedC>),
145                            typename Comp::DeferredBindingFunctors);
146     struct Op {
147       // Note that we do NOT call AddProvidedType here. We'll only know the right required type
148       // when the binding will be used.
149       using Result = Eval<Comp1>;
150       void operator()(FixedSizeVector<ComponentStorageEntry>&) {}
151       std::size_t numEntries() {
152         return 0;
153       }
154     };
155     using I = RemoveAnnotations(AnnotatedI);
156     using C = RemoveAnnotations(AnnotatedC);
157     using type =
158         If(IsSame(I, C), ConstructError(InterfaceBindingToSelfErrorTag, C),
159            If(Not(IsBaseOf(I, C)), ConstructError(NotABaseClassOfErrorTag, I, C),
160               If(Not(IsSame(I, NormalizeType(I))), ConstructError(NonClassTypeErrorTag, I, NormalizeUntilStable(I)),
161                  If(Not(IsSame(C, NormalizeType(C))),
162                     // We handle this case too, just to be on the safe side, but this should never happen.
163                     ConstructError(NonClassTypeErrorTag, C, NormalizeUntilStable(C)),
164                     If(IsInSet(AnnotatedI, typename Comp::Ps), ConstructError(TypeAlreadyBoundErrorTag, AnnotatedI),
165                        If(MapContainsKey(typename Comp::InterfaceBindings, AnnotatedI),
166                           ConstructError(TypeAlreadyBoundErrorTag, AnnotatedI), Op))))));
167   };
168 };
169 
170 struct ProcessInterfaceBinding {
171   template <typename Comp, typename AnnotatedI, typename AnnotatedC, typename NonConstBindingRequired>
172   struct apply {
173     using R = If(NonConstBindingRequired,
174                  AddProvidedTypeIgnoringInterfaceBindings(Comp, AnnotatedI, NonConstBindingRequired, Vector<AnnotatedC>,
175                                                           Vector<AnnotatedC>),
176                  AddProvidedTypeIgnoringInterfaceBindings(Comp, AnnotatedI, NonConstBindingRequired, Vector<AnnotatedC>,
177                                                           Vector<>));
178     struct ConstOp {
179       // This must be here (and not in AddDeferredInterfaceBinding) because the binding might be
180       // used to bind functors instead, so we might never need to add C to the requirements.
181       using Result = Eval<R>;
182       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
183         entries.push_back(
184             InjectorStorage::createComponentStorageEntryForConstBind<UnwrapType<AnnotatedI>, UnwrapType<AnnotatedC>>());
185       };
186 
187       std::size_t numEntries() {
188         return 1;
189       }
190     };
191     struct NonConstOp {
192       // This must be here (and not in AddDeferredInterfaceBinding) because the binding might be
193       // used to bind functors instead, so we might never need to add C to the requirements.
194       using Result = Eval<R>;
195       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
196         entries.push_back(
197             InjectorStorage::createComponentStorageEntryForBind<UnwrapType<AnnotatedI>, UnwrapType<AnnotatedC>>());
198       };
199 
200       std::size_t numEntries() {
201         return 1;
202       }
203     };
204     using type = PropagateError(R, If(NonConstBindingRequired, NonConstOp, ConstOp));
205   };
206 };
207 
208 struct AddInterfaceMultibinding {
209   template <typename Comp, typename AnnotatedI, typename AnnotatedC>
210   struct apply {
211     using I = RemoveAnnotations(AnnotatedI);
212     using C = RemoveAnnotations(AnnotatedC);
213     using R = AddRequirements(Comp, Vector<AnnotatedC>, Vector<AnnotatedC>);
214     struct Op {
215       using Result = Eval<R>;
216       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
217         entries.push_back(InjectorStorage::createComponentStorageEntryForMultibinding<UnwrapType<AnnotatedI>,
218                                                                                       UnwrapType<AnnotatedC>>());
219         entries.push_back(
220             InjectorStorage::createComponentStorageEntryForMultibindingVectorCreator<UnwrapType<AnnotatedI>>());
221       };
222 
223       std::size_t numEntries() {
224         return 2;
225       }
226     };
227     using type = If(Not(IsBaseOf(I, C)), ConstructError(NotABaseClassOfErrorTag, I, C), Op);
228   };
229 };
230 
231 template <typename AnnotatedSignature, typename Lambda, typename OptionalAnnotatedI>
232 struct PostProcessRegisterProviderHelper;
233 
234 template <typename AnnotatedSignature, typename Lambda, typename AnnotatedI>
235 struct PostProcessRegisterProviderHelper;
236 
237 template <typename AnnotatedSignature, typename Lambda, typename AnnotatedI>
238 struct PostProcessRegisterProviderHelper<AnnotatedSignature, Lambda, Type<AnnotatedI>> {
239   inline void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
240     entries.push_back(
241         InjectorStorage::createComponentStorageEntryForCompressedProvider<AnnotatedSignature, Lambda, AnnotatedI>());
242     entries.push_back(InjectorStorage::createComponentStorageEntryForProvider<AnnotatedSignature, Lambda>());
243   }
244 
245   std::size_t numEntries() {
246     return 2;
247   }
248 };
249 
250 template <typename AnnotatedSignature, typename Lambda>
251 struct PostProcessRegisterProviderHelper<AnnotatedSignature, Lambda, None> {
252   inline void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
253     entries.push_back(InjectorStorage::createComponentStorageEntryForProvider<AnnotatedSignature, Lambda>());
254   }
255 
256   std::size_t numEntries() {
257     return 1;
258   }
259 };
260 
261 // T can't be any injectable type, it must match the return type of the provider in one of
262 // the registerProvider() overloads in ComponentStorage.
263 struct PostProcessRegisterProvider {
264   template <typename Comp, typename AnnotatedSignature, typename Lambda>
265   struct apply {
266     using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature));
267     using OptionalAnnotatedI = FindValueInMap(typename Comp::InterfaceBindings, AnnotatedC);
268     struct Op {
269       using Result = Comp;
270 
271       using Helper = PostProcessRegisterProviderHelper<UnwrapType<AnnotatedSignature>, UnwrapType<Lambda>,
272                                                        Eval<OptionalAnnotatedI>>;
273       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
274         Helper()(entries);
275       }
276       std::size_t numEntries() {
277         return Helper().numEntries();
278       }
279     };
280     using type = Op;
281   };
282 };
283 
284 struct PreProcessRegisterProvider {
285   template <typename Comp, typename AnnotatedSignature, typename Lambda>
286   struct apply {
287     using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature);
288     using SignatureFromLambda = FunctionSignature(Lambda);
289 
290     using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature));
291     using AnnotatedCDeps = NormalizeTypeVector(SignatureArgs(AnnotatedSignature));
292     using R = AddProvidedType(Comp, AnnotatedC, Bool<true>, AnnotatedCDeps,
293                               Id<NormalizedNonConstTypesIn(SignatureArgs(AnnotatedSignature))>);
294     using type =
295         If(Not(IsSame(Signature, SignatureFromLambda)),
296            ConstructError(AnnotatedSignatureDifferentFromLambdaSignatureErrorTag, Signature, SignatureFromLambda),
297            PropagateError(
298                CheckInjectableType(RemoveAnnotations(SignatureType(AnnotatedSignature))),
299                PropagateError(
300                    CheckInjectableTypeVector(RemoveAnnotationsFromVector(AnnotatedCDeps)),
301                    PropagateError(
302                        CheckInjectableType(SignatureType(SignatureFromLambda)),
303                        PropagateError(
304                            CheckInjectableTypeVector(SignatureArgs(SignatureFromLambda)),
305                            If(And(IsPointer(SignatureType(SignatureFromLambda)),
306                                   And(IsAbstract(RemovePointer(SignatureType(SignatureFromLambda))),
307                                       Not(HasVirtualDestructor(RemovePointer(SignatureType(SignatureFromLambda)))))),
308                               ConstructError(ProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag,
309                                              RemovePointer(SignatureType(SignatureFromLambda))),
310                               ComponentFunctorIdentity(R)))))));
311   };
312 };
313 
314 // The registration is actually deferred until the PartialComponent is converted to a component.
315 struct DeferredRegisterProviderWithAnnotations {
316   template <typename Comp, typename AnnotatedSignature, typename Lambda>
317   struct apply {
318     using Comp1 = AddDeferredBinding(Comp, ComponentFunctor(PostProcessRegisterProvider, AnnotatedSignature, Lambda));
319     using type = PreProcessRegisterProvider(Comp1, AnnotatedSignature, Lambda);
320   };
321 };
322 
323 // The registration is actually deferred until the PartialComponent is converted to a component.
324 struct DeferredRegisterProvider {
325   template <typename Comp, typename Lambda>
326   struct apply {
327     using type = DeferredRegisterProviderWithAnnotations(Comp, FunctionSignature(Lambda), Lambda);
328   };
329 };
330 
331 // T can't be any injectable type, it must match the return type of the provider in one of
332 // the registerMultibindingProvider() overloads in ComponentStorage.
333 struct RegisterMultibindingProviderWithAnnotations {
334   template <typename Comp, typename AnnotatedSignature, typename Lambda>
335   struct apply {
336     using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature);
337     using SignatureFromLambda = FunctionSignature(Lambda);
338 
339     using AnnotatedArgs = SignatureArgs(AnnotatedSignature);
340     using AnnotatedArgVector = NormalizeTypeVector(AnnotatedArgs);
341     using NonConstRequirements = NormalizedNonConstTypesIn(AnnotatedArgs);
342     using R = AddRequirements(Comp, AnnotatedArgVector, NonConstRequirements);
343     struct Op {
344       using Result = Eval<R>;
345       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
346         entries.push_back(
347             InjectorStorage::createComponentStorageEntryForMultibindingProvider<UnwrapType<AnnotatedSignature>,
348                                                                                 UnwrapType<Lambda>>());
349         entries.push_back(InjectorStorage::createComponentStorageEntryForMultibindingVectorCreator<
350                           UnwrapType<Eval<NormalizeType(SignatureType(AnnotatedSignature))>>>());
351       }
352       std::size_t numEntries() {
353         return 2;
354       }
355     };
356     using type = If(
357         Not(IsValidSignature(AnnotatedSignature)), ConstructError(NotASignatureErrorTag, AnnotatedSignature),
358         PropagateError(
359             CheckInjectableType(RemoveAnnotations(SignatureType(AnnotatedSignature))),
360             PropagateError(
361                 CheckInjectableTypeVector(RemoveAnnotationsFromVector(SignatureArgs(AnnotatedSignature))),
362                 PropagateError(
363                     CheckInjectableType(SignatureType(SignatureFromLambda)),
364                     PropagateError(
365                         CheckInjectableTypeVector(SignatureArgs(SignatureFromLambda)),
366                         If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))),
367                            ConstructError(CannotConstructAbstractClassErrorTag,
368                                           RemoveAnnotations(SignatureType(AnnotatedSignature))),
369                            If(Not(IsSame(Signature, SignatureFromLambda)),
370                               ConstructError(AnnotatedSignatureDifferentFromLambdaSignatureErrorTag, Signature,
371                                              SignatureFromLambda),
372                               If(And(IsPointer(SignatureType(SignatureFromLambda)),
373                                      And(IsAbstract(RemovePointer(SignatureType(SignatureFromLambda))),
374                                          Not(HasVirtualDestructor(RemovePointer(SignatureType(SignatureFromLambda)))))),
375                                  ConstructError(
376                                      MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag,
377                                      RemovePointer(SignatureType(SignatureFromLambda))),
378                                  PropagateError(R, Op)))))))));
379   };
380 };
381 
382 // T can't be any injectable type, it must match the return type of the provider in one of
383 // the registerMultibindingProvider() overloads in ComponentStorage.
384 struct RegisterMultibindingProvider {
385   template <typename Comp, typename Lambda>
386   struct apply {
387     using type = RegisterMultibindingProviderWithAnnotations(Comp, FunctionSignature(Lambda), Lambda);
388   };
389 };
390 
391 // Non-assisted case.
392 template <int numAssistedBefore, int numNonAssistedBefore, typename Arg>
393 struct GetAssistedArg {
394   template <typename InjectedArgsTuple, typename UserProvidedArgsTuple>
395   inline Arg operator()(InjectedArgsTuple& injected_args, UserProvidedArgsTuple&) {
396     return std::get<numNonAssistedBefore>(injected_args);
397   }
398 };
399 
400 // Assisted case.
401 template <int numAssistedBefore, int numNonAssistedBefore, typename Arg>
402 struct GetAssistedArg<numAssistedBefore, numNonAssistedBefore, Assisted<Arg>> {
403   template <typename InjectedArgsTuple, typename UserProvidedArgsTuple>
404   inline Arg operator()(InjectedArgsTuple&, UserProvidedArgsTuple& user_provided_args) {
405     return std::get<numAssistedBefore>(user_provided_args);
406   }
407 };
408 
409 struct RegisterFactoryHelper {
410 
411   template <typename Comp, typename DecoratedSignature, typename Lambda,
412             // std::function<InjectedSignature> is the injected type (possibly with an Annotation<> wrapping it)
413             typename InjectedSignature, typename RequiredLambdaSignature, typename InjectedAnnotatedArgs,
414             // The types that are injected, unwrapped from any Annotation<>.
415             typename InjectedArgs, typename IndexSequence>
416   struct apply;
417 
418   template <typename Comp, typename DecoratedSignature, typename Lambda, typename NakedC,
419             typename... NakedUserProvidedArgs, typename... NakedAllArgs, typename... InjectedAnnotatedArgs,
420             typename... NakedInjectedArgs, typename... Indexes>
421   struct apply<Comp, DecoratedSignature, Lambda, Type<NakedC(NakedUserProvidedArgs...)>, Type<NakedC(NakedAllArgs...)>,
422                Vector<InjectedAnnotatedArgs...>, Vector<Type<NakedInjectedArgs>...>, Vector<Indexes...>> {
423     // Here we call "decorated" the types that might be wrapped in Annotated<> or Assisted<>,
424     // while we call "annotated" the ones that might only be wrapped in Annotated<> (but not Assisted<>).
425     using AnnotatedT = SignatureType(DecoratedSignature);
426     using T = RemoveAnnotations(AnnotatedT);
427     using DecoratedArgs = SignatureArgs(DecoratedSignature);
428     using NakedInjectedSignature = NakedC(NakedUserProvidedArgs...);
429     using NakedRequiredSignature = NakedC(NakedAllArgs...);
430     using NakedFunctor = std::function<NakedInjectedSignature>;
431     // This is usually the same as Functor, but this might be annotated.
432     using AnnotatedFunctor = CopyAnnotation(AnnotatedT, Type<NakedFunctor>);
433     using FunctorDeps = NormalizeTypeVector(Vector<InjectedAnnotatedArgs...>);
434     using FunctorNonConstDeps = NormalizedNonConstTypesIn(Vector<InjectedAnnotatedArgs...>);
435     using R = AddProvidedType(Comp, AnnotatedFunctor, Bool<true>, FunctorDeps, FunctorNonConstDeps);
436     struct Op {
437       using Result = Eval<R>;
438       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
439         auto function_provider = [](NakedInjectedArgs... args) {
440           auto injected_args = std::make_tuple(args...);
441           auto object_provider = [injected_args](NakedUserProvidedArgs... params) mutable {
442             auto user_provided_args = std::tie(params...);
443             // These are unused if they are 0-arg tuples. Silence the unused-variable warnings anyway.
444             (void)injected_args;
445             (void)user_provided_args;
446 
447             return LambdaInvoker::invoke<UnwrapType<Lambda>, NakedAllArgs...>(
448                 GetAssistedArg<
449                     Eval<NumAssistedBefore(Indexes, DecoratedArgs)>::value,
450                     getIntValue<Indexes>() - Eval<NumAssistedBefore(Indexes, DecoratedArgs)>::value,
451                     // Note that the Assisted<> wrapper (if any) remains, we just remove any wrapping Annotated<>.
452                     UnwrapType<Eval<RemoveAnnotations(GetNthType(Indexes, DecoratedArgs))>>>()(injected_args,
453                                                                                                user_provided_args)...);
454           };
455           return NakedFunctor(object_provider);
456         };
457         entries.push_back(InjectorStorage::createComponentStorageEntryForProvider<
458                           UnwrapType<Eval<ConsSignatureWithVector(AnnotatedFunctor, Vector<InjectedAnnotatedArgs...>)>>,
459                           decltype(function_provider)>());
460       }
461       std::size_t numEntries() {
462         return 1;
463       }
464     };
465     // The first two IsValidSignature checks are a bit of a hack, they are needed to make the F2/RealF2 split
466     // work in the caller (we need to allow Lambda to be a function type).
467     using type = If(Not(IsSame(Type<NakedRequiredSignature>, FunctionSignature(Lambda))),
468                     ConstructError(FunctorSignatureDoesNotMatchErrorTag, Type<NakedRequiredSignature>,
469                                    FunctionSignature(Lambda)),
470                     If(IsPointer(T), ConstructError(FactoryReturningPointerErrorTag, DecoratedSignature),
471                        PropagateError(R, Op)));
472   };
473 };
474 
475 struct RegisterFactory {
476   template <typename Comp, typename DecoratedSignature, typename Lambda>
477   struct apply {
478     using LambdaReturnType = SignatureType(FunctionSignature(Lambda));
479     using type =
480         If(Not(IsValidSignature(DecoratedSignature)), ConstructError(NotASignatureErrorTag, DecoratedSignature),
481            PropagateError(
482                CheckInjectableType(RemoveAnnotations(SignatureType(DecoratedSignature))),
483                PropagateError(
484                    CheckInjectableTypeVector(
485                        RemoveAnnotationsFromVector(RemoveAssisted(SignatureArgs(DecoratedSignature)))),
486                    If(IsAbstract(RemoveAnnotations(SignatureType(DecoratedSignature))),
487                       // We error out early in this case. Calling RegisterFactoryHelper would also produce an error, but
488                       // it'd be
489                       // much less user-friendly.
490                       ConstructError(CannotConstructAbstractClassErrorTag,
491                                      RemoveAnnotations(SignatureType(DecoratedSignature))),
492                       If(Not(Or(IsEmpty(Lambda), IsValidSignature(Lambda))),
493                          ConstructError(LambdaWithCapturesErrorTag, Lambda),
494                          If(Not(Or(IsTriviallyCopyable(Lambda), IsValidSignature(Lambda))),
495                             ConstructError(NonTriviallyCopyableLambdaErrorTag, Lambda),
496                             If(And(IsUniquePtr(LambdaReturnType),
497                                    And(IsAbstract(RemoveUniquePtr(LambdaReturnType)),
498                                        Not(HasVirtualDestructor(RemoveUniquePtr(LambdaReturnType))))),
499                                ConstructError(RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorErrorTag,
500                                               RemoveUniquePtr(LambdaReturnType)),
501                                RegisterFactoryHelper(
502                                    Comp, DecoratedSignature, Lambda,
503                                    InjectedSignatureForAssistedFactory(DecoratedSignature),
504                                    RequiredLambdaSignatureForAssistedFactory(DecoratedSignature),
505                                    RemoveAssisted(SignatureArgs(DecoratedSignature)),
506                                    RemoveAnnotationsFromVector(RemoveAssisted(SignatureArgs(DecoratedSignature))),
507                                    GenerateIntSequence(
508                                        VectorSize(RequiredLambdaArgsForAssistedFactory(DecoratedSignature)))))))))));
509   };
510 };
511 
512 struct PostProcessRegisterConstructor;
513 
514 template <typename AnnotatedSignature, typename OptionalAnnotatedI>
515 struct PostProcessRegisterConstructorHelper;
516 
517 template <typename AnnotatedSignature, typename AnnotatedI>
518 struct PostProcessRegisterConstructorHelper;
519 
520 template <typename AnnotatedSignature, typename AnnotatedI>
521 struct PostProcessRegisterConstructorHelper<AnnotatedSignature, Type<AnnotatedI>> {
522   inline void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
523     entries.push_back(
524         InjectorStorage::createComponentStorageEntryForCompressedConstructor<AnnotatedSignature, AnnotatedI>());
525     entries.push_back(InjectorStorage::createComponentStorageEntryForConstructor<AnnotatedSignature>());
526   }
527   std::size_t numEntries() {
528     return 2;
529   }
530 };
531 
532 template <typename AnnotatedSignature>
533 struct PostProcessRegisterConstructorHelper<AnnotatedSignature, None> {
534   inline void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
535     entries.push_back(InjectorStorage::createComponentStorageEntryForConstructor<AnnotatedSignature>());
536   }
537   std::size_t numEntries() {
538     return 1;
539   }
540 };
541 
542 struct PostProcessRegisterConstructor {
543   template <typename Comp, typename AnnotatedSignature>
544   struct apply {
545     struct type {
546       using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature));
547       using Result = Comp;
548       using Helper =
549           PostProcessRegisterConstructorHelper<UnwrapType<AnnotatedSignature>,
550                                                Eval<FindValueInMap(typename Comp::InterfaceBindings, AnnotatedC)>>;
551       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
552         Helper()(entries);
553       }
554       std::size_t numEntries() {
555         return Helper().numEntries();
556       }
557     };
558   };
559 };
560 
561 struct PreProcessRegisterConstructor {
562   template <typename Comp, typename AnnotatedSignature>
563   struct apply {
564     using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature);
565     using C = SignatureType(Signature);
566     using Args = SignatureArgs(Signature);
567     using AnnotatedT = SignatureType(AnnotatedSignature);
568     using AnnotatedArgs = SignatureArgs(AnnotatedSignature);
569     using AnnotatedC = NormalizeType(AnnotatedT);
570     using CDeps = NormalizeTypeVector(AnnotatedArgs);
571     using CNonConstDeps = NormalizedNonConstTypesIn(AnnotatedArgs);
572     using R = AddProvidedType(Comp, AnnotatedC, Bool<true>, CDeps, CNonConstDeps);
573     using type = If(
574         Not(IsValidSignature(AnnotatedSignature)), ConstructError(NotASignatureErrorTag, AnnotatedSignature),
575         PropagateError(CheckInjectableType(RemoveAnnotations(C)),
576                        PropagateError(CheckInjectableTypeVector(RemoveAnnotationsFromVector(Args)),
577                                       If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))),
578                                          ConstructError(CannotConstructAbstractClassErrorTag,
579                                                         RemoveAnnotations(SignatureType(AnnotatedSignature))),
580                                          If(Not(IsConstructibleWithVector(C, Args)),
581                                             ConstructError(NoConstructorMatchingInjectSignatureErrorTag, C, Signature),
582                                             PropagateError(R, ComponentFunctorIdentity(R)))))));
583   };
584 };
585 
586 struct DeferredRegisterConstructor {
587   template <typename Comp, typename AnnotatedSignature>
588   struct apply {
589     using Comp1 = AddDeferredBinding(Comp, ComponentFunctor(PostProcessRegisterConstructor, AnnotatedSignature));
590     using type = PreProcessRegisterConstructor(Comp1, AnnotatedSignature);
591   };
592 };
593 
594 struct RegisterInstance {
595   template <typename Comp, typename AnnotatedC, typename C, typename IsNonConst>
596   struct apply {
597     using R = AddProvidedType(Comp, AnnotatedC, IsNonConst, Vector<>, Vector<>);
598     struct Op {
599       using Result = Eval<R>;
600       void operator()(FixedSizeVector<ComponentStorageEntry>&) {}
601       std::size_t numEntries() {
602         return 0;
603       }
604     };
605     using type = PropagateError(
606         CheckNormalizedTypes(ConsVector(RemoveAnnotations(AnnotatedC))),
607         PropagateError(
608             CheckNormalizedTypes(ConsVector(C)),
609             If(Not(IsSame(C, NormalizeType(C))), ConstructError(NonClassTypeErrorTag, C, NormalizeUntilStable(C)),
610                If(Not(IsSame(RemoveAnnotations(AnnotatedC), NormalizeType(RemoveAnnotations(AnnotatedC)))),
611                   ConstructError(NonClassTypeErrorTag, RemoveAnnotations(AnnotatedC),
612                                  NormalizeUntilStable(RemoveAnnotations(C))),
613                   // The IsSame check is not redundant because IsBaseOf returns false for non-class types (e.g. int).
614                   If(Not(Or(IsSame(RemoveAnnotations(AnnotatedC), C), IsBaseOf(RemoveAnnotations(AnnotatedC), C))),
615                      ConstructError(TypeMismatchInBindInstanceErrorTag, RemoveAnnotations(AnnotatedC), C),
616                      PropagateError(R, Op))))));
617   };
618 };
619 
620 struct RegisterConstructorAsValueFactory {
621   template <typename Comp, typename DecoratedSignature,
622             typename RequiredSignature = Eval<RequiredLambdaSignatureForAssistedFactory(DecoratedSignature)>>
623   struct apply;
624 
625   template <typename Comp, typename DecoratedSignature, typename NakedT, typename... NakedArgs>
626   struct apply<Comp, DecoratedSignature, Type<NakedT(NakedArgs...)>> {
627     using RequiredSignature = Type<NakedT(NakedArgs...)>;
628     using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature);
629     struct Op {
630       using Result = Eval<GetResult(Op1)>;
631       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
632         auto provider = [](NakedArgs... args) { return NakedT(std::forward<NakedArgs>(args)...); };
633         using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>);
634         FruitStaticAssert(IsSame(GetResult(Op1), GetResult(RealOp)));
635         Eval<RealOp>()(entries);
636       }
637       std::size_t numEntries() {
638 #if FRUIT_EXTRA_DEBUG
639         auto provider = [](NakedArgs... args) { return NakedT(std::forward<NakedArgs>(args)...); };
640         using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>);
641         FruitAssert(Eval<Op1>().numEntries() == Eval<RealOp>().numEntries());
642 #endif
643         return Eval<Op1>().numEntries();
644       }
645     };
646     using type = PropagateError(Op1, Op);
647   };
648 };
649 
650 struct RegisterConstructorAsUniquePtrFactory {
651   template <typename Comp, typename DecoratedSignature,
652             typename RequiredSignature = Eval<RequiredLambdaSignatureForAssistedFactory(DecoratedSignature)>>
653   struct apply;
654 
655   template <typename Comp, typename DecoratedSignature, typename NakedT, typename... NakedArgs>
656   struct apply<Comp, DecoratedSignature, Type<std::unique_ptr<NakedT>(NakedArgs...)>> {
657     using RequiredSignature = Type<std::unique_ptr<NakedT>(NakedArgs...)>;
658     using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature);
659     struct Op {
660       using Result = Eval<GetResult(Op1)>;
661       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
662         auto provider = [](NakedArgs... args) {
663           return std::unique_ptr<NakedT>(new NakedT(std::forward<NakedArgs>(args)...));
664         };
665         using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>);
666         FruitStaticAssert(IsSame(GetResult(Op1), GetResult(RealOp)));
667         Eval<RealOp>()(entries);
668       };
669       std::size_t numEntries() {
670 #if FRUIT_EXTRA_DEBUG
671         auto provider = [](NakedArgs... args) {
672           return std::unique_ptr<NakedT>(new NakedT(std::forward<NakedArgs>(args)...));
673         };
674         using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>);
675         FruitAssert(Eval<Op1>().numEntries() == Eval<RealOp>().numEntries());
676 #endif
677         return Eval<Op1>().numEntries();
678       }
679     };
680 
681     using type = PropagateError(Op1, Op);
682   };
683 };
684 
685 struct InstallComponent {
686   template <typename Comp, typename OtherComp>
687   struct apply {
688     using new_RsSuperset = SetUnion(typename OtherComp::RsSuperset, typename Comp::RsSuperset);
689     using new_Ps = SetUncheckedUnion(typename OtherComp::Ps, typename Comp::Ps);
690     using new_NonConstRsPs = SetUnion(typename OtherComp::NonConstRsPs, typename Comp::NonConstRsPs);
691 #if !FRUIT_NO_LOOP_CHECK
692     using new_Deps = ConcatVectors(typename OtherComp::Deps, typename Comp::Deps);
693 #endif
694     FruitStaticAssert(IsSame(typename OtherComp::InterfaceBindings, Vector<>));
695     using new_InterfaceBindings = typename Comp::InterfaceBindings;
696 
697     FruitStaticAssert(IsSame(typename OtherComp::DeferredBindingFunctors, EmptyList));
698     using new_DeferredBindingFunctors = typename Comp::DeferredBindingFunctors;
699 
700     using R = ConsComp(new_RsSuperset, new_Ps, new_NonConstRsPs,
701 #if !FRUIT_NO_LOOP_CHECK
702                        new_Deps,
703 #endif
704                        new_InterfaceBindings, new_DeferredBindingFunctors);
705     struct Op {
706       using Result = Eval<R>;
707       void operator()(FixedSizeVector<ComponentStorageEntry>&) {}
708       std::size_t numEntries() {
709         return 0;
710       }
711     };
712     using InterfacePs = VectorToSetUnchecked(GetMapKeys(typename Comp::InterfaceBindings));
713     using AllPs = SetUncheckedUnion(InterfacePs, typename Comp::Ps);
714     using DuplicateTypes = SetIntersection(typename OtherComp::Ps, AllPs);
715     using CompConstPs = SetDifference(typename Comp::Ps, typename Comp::NonConstRsPs);
716     using CompRs = SetDifference(typename Comp::RsSuperset, typename Comp::Ps);
717     using CompNonConstRs = SetIntersection(CompRs, typename Comp::NonConstRsPs);
718 
719     using OtherCompConstPs = SetDifference(typename OtherComp::Ps, typename OtherComp::NonConstRsPs);
720     using OtherCompRs = SetDifference(typename OtherComp::RsSuperset, typename OtherComp::Ps);
721     using OtherCompNonConstRs = SetIntersection(OtherCompRs, typename OtherComp::NonConstRsPs);
722 
723     using type = If(Not(IsDisjoint(typename OtherComp::Ps, AllPs)),
724                     ConstructErrorWithArgVector(DuplicateTypesInComponentErrorTag, SetToVector(DuplicateTypes)),
725                     If(Not(IsDisjoint(CompConstPs, OtherCompNonConstRs)),
726                        ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag,
727                                       GetArbitrarySetElement(SetIntersection(CompConstPs, OtherCompNonConstRs))),
728                        If(Not(IsDisjoint(CompNonConstRs, OtherCompConstPs)),
729                           ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag,
730                                          GetArbitrarySetElement(SetIntersection(CompNonConstRs, OtherCompConstPs))),
731                           Op)));
732   };
733 };
734 
735 struct InstallComponentHelper {
736   template <typename Comp, typename... OtherCompParams>
737   struct apply {
738     using OtherComp = ConstructComponentImpl(OtherCompParams...);
739     using type = InstallComponent(Comp, OtherComp);
740   };
741 };
742 
743 struct InstallComponentFunctions {
744     template <typename Comp, typename... ComponentFunctions>
745     struct apply;
746 
747     template <typename Comp>
748     struct apply<Comp> {
749       using type = ComponentFunctorIdentity(Comp);
750     };
751 
752     template <typename Comp, typename... ComponentParams, typename... ComponentFunctionArgs, typename... ComponentFunctions>
753     struct apply<Comp, Type<fruit::ComponentFunction<fruit::Component<ComponentParams...>, ComponentFunctionArgs...>>, ComponentFunctions...> {
754       using type =
755           Call(
756               Compose2ComponentFunctors(
757                   ComponentFunctor(InstallComponent, ConstructComponentImpl(Type<ComponentParams>...)),
758                   ComponentFunctor(InstallComponentFunctions, ComponentFunctions...)),
759               Comp);
760     };
761 
762     template <typename Comp, typename T, typename... ComponentFunctions>
763     struct apply<Comp, T, ComponentFunctions...> {
764         using type = ConstructError(IncorrectArgTypePassedToInstallComponentFuntionsErrorTag, T);
765     };
766 };
767 
768 // CatchAll(PropagateError(Expr, Bool<false>), IsErrorExceptionHandler) evaluates to Bool<true> if Expr throws an error,
769 // and Bool<false> otherwise.
770 struct IsErrorExceptionHandler {
771   template <typename E>
772   struct apply {
773     using type = Bool<true>;
774   };
775 };
776 
777 struct ConvertComponent {
778   template <typename SourceComp, typename DestComp>
779   struct apply {
780     using SourcePs = typename SourceComp::Ps;
781     using DestPs = typename DestComp::Ps;
782     using SourceRs = SetDifference(typename SourceComp::RsSuperset, typename SourceComp::Ps);
783     using DestRs = SetDifference(typename DestComp::RsSuperset, typename DestComp::Ps);
784     using NonConstSourceRs = SetIntersection(SourceRs, typename SourceComp::NonConstRsPs);
785     using NonConstDestPs = SetIntersection(DestPs, typename DestComp::NonConstRsPs);
786     using NonConstDestRs = SetIntersection(DestRs, typename DestComp::NonConstRsPs);
787 
788     using ConstSourcePs = SetDifference(SourcePs, typename SourceComp::NonConstRsPs);
789     using ConstDestRs = SetDifference(DestRs, typename DestComp::NonConstRsPs);
790 
791     // We need to register:
792     // * All the types provided by the new component
793     // * All the types required by the old component
794     // except:
795     // * The ones already provided by the old component (if they have the right constness).
796     // * The ones required by the new one (if they have the right constness).
797     using ToRegister = SetUnion(
798         // The types that we must provide and aren't currently provided
799         SetDifference(SetUnion(DestPs, SourceRs), SetUnion(DestRs, SourcePs)),
800         // And the ones that are currently provided as const but that we need to provide as non-const
801         SetIntersection(SetUnion(NonConstDestPs, NonConstSourceRs), SetUnion(ConstDestRs, ConstSourcePs)));
802     using NonConstTypesToRegister = SetIntersection(ToRegister, SetUnion(typename SourceComp::NonConstRsPs,
803                                                                          typename DestComp::NonConstRsPs));
804     using type = EnsureProvidedTypes(SourceComp, DestRs, NonConstDestRs, SetToVector(ToRegister),
805                                      NonConstTypesToRegister);
806 
807 // Not needed, just double-checking.
808 // Uses FruitStaticAssert instead of FruitDelegateCheck so that it's checked only in debug mode.
809 #if FRUIT_EXTRA_DEBUG
810     FruitDelegateCheck(
811         If(CatchAll(PropagateError(type, PropagateError(Id<GetResult(type)>, Bool<false>)), IsErrorExceptionHandler),
812            // We're going to return an error soon anyway, we don't want to interfere by reporting this one.
813            None, CheckComponentEntails(GetResult(type), DestComp)));
814 #endif // FRUIT_EXTRA_DEBUG
815   };
816 };
817 
818 struct ProcessDeferredBindings {
819   template <typename Comp>
820   struct apply;
821 
822   template <typename RsSupersetParam, typename PsParam, typename NonConstRsPsParam,
823 #if !FRUIT_NO_LOOP_CHECK
824             typename DepsParam,
825 #endif
826             typename InterfaceBindingsParam, typename DeferredBindingFunctors>
827   struct apply<Comp<RsSupersetParam, PsParam, NonConstRsPsParam,
828 #if !FRUIT_NO_LOOP_CHECK
829                     DepsParam,
830 #endif
831                     InterfaceBindingsParam, DeferredBindingFunctors>> {
832     // Comp1 is the same as Comp, but without the DeferredBindingFunctors.
833     using Comp1 = ConsComp(RsSupersetParam, PsParam, NonConstRsPsParam,
834 #if !FRUIT_NO_LOOP_CHECK
835                            DepsParam,
836 #endif
837                            InterfaceBindingsParam, EmptyList);
838     using type = Call(FoldList(DeferredBindingFunctors, Compose2ComponentFunctors, ComponentFunctorIdentity), Comp1);
839   };
840 };
841 
842 template <typename AnnotatedCFunctor, typename AnnotatedCUniquePtrFunctor>
843 struct AutoRegisterFactoryHelperErrorHandler {
844   template <typename E>
845   struct apply {
846     using type = E;
847   };
848 
849   template <typename T>
850   struct apply<Error<NoBindingFoundErrorTag, T>> {
851     using type = If(IsSame(Type<T>, AnnotatedCFunctor), ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor),
852                     ConstructError(NoBindingFoundErrorTag, Type<T>));
853   };
854 
855   template <typename T1, typename T2>
856   struct apply<Error<NoBindingFoundForAbstractClassErrorTag, T1, T2>> {
857     using type = If(IsSame(Type<T1>, AnnotatedCFunctor), ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor),
858                     ConstructError(NoBindingFoundForAbstractClassErrorTag, Type<T1>, Type<T2>));
859   };
860 };
861 
862 struct AutoRegisterFactoryHelper {
863 
864   // General case, no way to bind it.
865   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename InterfaceBinding,
866             typename has_inject_annotation, typename is_abstract, typename C, typename AnnotatedSignature,
867             typename... Args>
868   struct apply {
869     using AnnotatedC = SignatureType(AnnotatedSignature);
870     using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature));
871     using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor);
872     using type = If(IsAbstract(C), ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, C),
873                     ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor));
874   };
875 
876   // No way to bind it (we need this specialization too to ensure that the specialization below
877   // is not chosen for AnnotatedC=None).
878   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename unused1,
879             typename unused2, typename NakedI, typename AnnotatedSignature, typename... Args>
880   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, unused1, unused2,
881                Type<std::unique_ptr<NakedI>>, AnnotatedSignature, Args...> {
882     using AnnotatedC = SignatureType(AnnotatedSignature);
883     using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature));
884     using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor);
885     using type = If(IsAbstract(Type<NakedI>),
886                     ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, Type<NakedI>),
887                     ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor));
888   };
889 
890   // AnnotatedI has an interface binding, use it and look for a factory that returns the type that AnnotatedI is bound
891   // to.
892   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedC,
893             typename unused1, typename unused2, typename NakedI, typename AnnotatedSignature, typename... Args>
894   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, AnnotatedC, unused1, unused2,
895                Type<std::unique_ptr<NakedI>>, AnnotatedSignature, Args...> {
896     using I = Type<NakedI>;
897     using AnnotatedI = CopyAnnotation(SignatureType(AnnotatedSignature), I);
898     using C = RemoveAnnotations(AnnotatedC);
899     using IFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(I), Args...));
900     using CFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...));
901     using AnnotatedIFunctor = CopyAnnotation(AnnotatedI, IFunctor);
902     using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor);
903 
904     using ProvidedSignature = ConsSignature(AnnotatedIFunctor,
905                                             CopyAnnotation(AnnotatedC, ConsConstReference(CFunctor)));
906     using LambdaSignature = ConsSignature(IFunctor, ConsConstReference(CFunctor));
907 
908     using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, TargetNonConstRequirements, AnnotatedCFunctor,
909                                 Bool<false>);
910     using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature);
911     using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature);
912     using R = Call(ComposeFunctors(F1, F2, F3), Comp);
913     struct Op {
914       using Result = Eval<GetResult(R)>;
915       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
916         using NakedC = UnwrapType<Eval<C>>;
917         auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) {
918           return UnwrapType<Eval<IFunctor>>([=](typename TypeUnwrapper<Args>::type... args) {
919             NakedC* c = fun(args...).release();
920             NakedI* i = static_cast<NakedI*>(c);
921             return std::unique_ptr<NakedI>(i);
922           });
923         };
924         using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
925         using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
926         using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp);
927         FruitStaticAssert(IsSame(GetResult(RealOp), GetResult(R)));
928         Eval<RealOp>()(entries);
929       }
930       std::size_t numEntries() {
931 #if FRUIT_EXTRA_DEBUG
932         using NakedC = UnwrapType<Eval<C>>;
933         auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) {
934           return UnwrapType<Eval<IFunctor>>([=](typename TypeUnwrapper<Args>::type... args) {
935             NakedC* c = fun(args...).release();
936             NakedI* i = static_cast<NakedI*>(c);
937             return std::unique_ptr<NakedI>(i);
938           });
939         };
940         using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
941         using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
942         using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp);
943         FruitAssert(Eval<R>().numEntries() == Eval<RealOp>().numEntries());
944 #endif
945         return Eval<R>().numEntries();
946       }
947     };
948     using type = PropagateError(R, If(Not(HasVirtualDestructor(I)),
949                                       ConstructError(FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorErrorTag,
950                                                      IFunctor, CFunctor),
951                                       Op));
952   };
953 
954   // C doesn't have an interface binding as interface, nor an INJECT annotation, and is not an abstract class.
955   // Bind std::function<unique_ptr<C>(Args...)> to std::function<C(Args...)> (possibly with annotations).
956   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename NakedC,
957             typename AnnotatedSignature, typename... Args>
958   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, Bool<false>, Bool<false>,
959                Type<std::unique_ptr<NakedC>>, AnnotatedSignature, Args...> {
960     using C = Type<NakedC>;
961     using CFunctor = ConsStdFunction(ConsSignature(C, Args...));
962     using CUniquePtrFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...));
963     using AnnotatedCUniquePtr = SignatureType(AnnotatedSignature);
964     using AnnotatedC = CopyAnnotation(AnnotatedCUniquePtr, C);
965     using AnnotatedCFunctor = CopyAnnotation(AnnotatedCUniquePtr, CFunctor);
966     using AnnotatedCUniquePtrFunctor = CopyAnnotation(AnnotatedCUniquePtr, CUniquePtrFunctor);
967     using AnnotatedCFunctorRef = CopyAnnotation(AnnotatedCUniquePtr, ConsConstReference(CFunctor));
968 
969     using ProvidedSignature = ConsSignature(AnnotatedCUniquePtrFunctor, AnnotatedCFunctorRef);
970     using LambdaSignature = ConsSignature(CUniquePtrFunctor, ConsConstReference(CFunctor));
971 
972     using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, TargetNonConstRequirements, AnnotatedCFunctor,
973                                 Bool<false>);
974     using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature);
975     using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature);
976     using R = Call(ComposeFunctors(F1, F2, F3), Comp);
977     struct Op {
978       using Result = Eval<GetResult(R)>;
979       void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
980         auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) {
981           return UnwrapType<Eval<CUniquePtrFunctor>>([=](typename TypeUnwrapper<Args>::type... args) {
982             NakedC* c = new NakedC(fun(args...));
983             return std::unique_ptr<NakedC>(c);
984           });
985         };
986         using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
987         using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
988         using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp);
989         FruitStaticAssert(IsSame(GetResult(RealOp), GetResult(R)));
990         Eval<RealOp>()(entries);
991       }
992       std::size_t numEntries() {
993 #if FRUIT_EXTRA_DEBUG
994         auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) {
995           return UnwrapType<Eval<CUniquePtrFunctor>>([=](typename TypeUnwrapper<Args>::type... args) {
996             NakedC* c = new NakedC(fun(args...));
997             return std::unique_ptr<NakedC>(c);
998           });
999         };
1000         using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
1001         using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>);
1002         using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp);
1003         FruitAssert(Eval<R>().numEntries() == Eval<RealOp>().numEntries());
1004 #endif
1005         return Eval<R>().numEntries();
1006       }
1007     };
1008 
1009     using ErrorHandler =
1010         AutoRegisterFactoryHelperErrorHandler<Eval<AnnotatedCFunctor>, Eval<AnnotatedCUniquePtrFunctor>>;
1011 
1012     // If we are about to report a NoBindingFound/NoBindingFoundForAbstractClass error for AnnotatedCFunctor,
1013     // report one for std::function<std::unique_ptr<C>(Args...)> instead,
1014     // otherwise we'd report an error about a type that the user doesn't expect.
1015     using type = PropagateError(Catch(Catch(R, NoBindingFoundErrorTag, ErrorHandler),
1016                                       NoBindingFoundForAbstractClassErrorTag, ErrorHandler),
1017                                 Op);
1018   };
1019 
1020   // C has an Inject typedef, use it. unique_ptr case.
1021   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename unused,
1022             typename NakedC, typename AnnotatedSignature, typename... Args>
1023   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, Bool<true>, unused,
1024                Type<std::unique_ptr<NakedC>>, AnnotatedSignature, Args...> {
1025     using AnnotatedCUniquePtr = SignatureType(AnnotatedSignature);
1026     using AnnotatedC = CopyAnnotation(AnnotatedCUniquePtr, RemoveUniquePtr(RemoveAnnotations(AnnotatedCUniquePtr)));
1027     using DecoratedSignatureReturningValue = GetInjectAnnotation(AnnotatedC);
1028     using DecoratedSignature = ConsSignatureWithVector(AnnotatedCUniquePtr,
1029                                                        SignatureArgs(DecoratedSignatureReturningValue));
1030     using DecoratedSignatureArgs = SignatureArgs(DecoratedSignature);
1031     using ActualSignatureInInjectionTypedef = ConsSignatureWithVector(SignatureType(DecoratedSignature),
1032                                                                       RemoveNonAssisted(DecoratedSignatureArgs));
1033     using NonAssistedArgs = RemoveAssisted(DecoratedSignatureArgs);
1034 
1035     using F1 = ComponentFunctor(RegisterConstructorAsUniquePtrFactory, DecoratedSignature);
1036     using F2 = ComponentFunctor(EnsureProvidedTypes, TargetRequirements, TargetNonConstRequirements,
1037                                 NormalizeTypeVector(NonAssistedArgs), NormalizedNonConstTypesIn(NonAssistedArgs));
1038 
1039     using type = If(Not(IsSame(AnnotatedSignature, ActualSignatureInInjectionTypedef)),
1040                     ConstructError(FunctorSignatureDoesNotMatchErrorTag, AnnotatedSignature,
1041                                    ActualSignatureInInjectionTypedef),
1042                     Call(ComposeFunctors(F1, F2), Comp));
1043   };
1044 
1045   // C has an Inject typedef, use it. Value (not unique_ptr) case.
1046   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename unused,
1047             typename NakedC, typename AnnotatedSignature, typename... Args>
1048   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, Bool<true>, unused, Type<NakedC>,
1049                AnnotatedSignature, Args...> {
1050     using AnnotatedC = SignatureType(AnnotatedSignature);
1051     using DecoratedSignature = GetInjectAnnotation(AnnotatedC);
1052     using DecoratedSignatureArgs = SignatureArgs(DecoratedSignature);
1053     using ActualSignatureInInjectionTypedef = ConsSignatureWithVector(SignatureType(DecoratedSignature),
1054                                                                       RemoveNonAssisted(DecoratedSignatureArgs));
1055     using NonAssistedArgs = RemoveAssisted(DecoratedSignatureArgs);
1056 
1057     using F1 = ComponentFunctor(RegisterConstructorAsValueFactory, DecoratedSignature);
1058     using F2 = ComponentFunctor(EnsureProvidedTypes, TargetRequirements, TargetNonConstRequirements,
1059                                 NormalizeTypeVector(NonAssistedArgs), NormalizedNonConstTypesIn(NonAssistedArgs));
1060 
1061     using type = If(Not(IsSame(AnnotatedSignature, ActualSignatureInInjectionTypedef)),
1062                     ConstructError(FunctorSignatureDoesNotMatchErrorTag, AnnotatedSignature,
1063                                    ActualSignatureInInjectionTypedef),
1064                     Call(ComposeFunctors(F1, F2), Comp));
1065   };
1066 };
1067 
1068 struct AutoRegister {
1069   // The types in TargetRequirements will not be auto-registered.
1070   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedC>
1071   struct apply;
1072 
1073   // Tries to register C by looking for a typedef called Inject inside C.
1074   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedC>
1075   struct apply {
1076     using CHasInjectAnnotation = HasInjectAnnotation(RemoveAnnotations(AnnotatedC));
1077     using Inject = GetInjectAnnotation(AnnotatedC);
1078     using CRequirements = NormalizeTypeVector(SignatureArgs(Inject));
1079     using CNonConstRequirements = NormalizedNonConstTypesIn(SignatureArgs(Inject));
1080     using F = ComposeFunctors(ComponentFunctor(PreProcessRegisterConstructor, Inject),
1081                               ComponentFunctor(PostProcessRegisterConstructor, Inject),
1082                               ComponentFunctor(EnsureProvidedTypes, TargetRequirements, TargetNonConstRequirements,
1083                                                CRequirements, CNonConstRequirements));
1084     using type = If(CHasInjectAnnotation, Call(F, Comp), ConstructNoBindingFoundError(AnnotatedC));
1085   };
1086 
1087   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename NakedC,
1088             typename... NakedArgs>
1089   struct apply<Comp, TargetRequirements, TargetNonConstRequirements, Type<std::function<NakedC(NakedArgs...)>>> {
1090     using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements,
1091                                            FindInMap(typename Comp::InterfaceBindings, Type<NakedC>),
1092                                            HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>), Type<NakedC>,
1093                                            Type<NakedC(NakedArgs...)>, Id<RemoveAnnotations(Type<NakedArgs>)>...);
1094   };
1095 
1096   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename NakedC,
1097             typename... NakedArgs>
1098   struct apply<Comp, TargetRequirements, TargetNonConstRequirements,
1099                Type<std::function<std::unique_ptr<NakedC>(NakedArgs...)>>> {
1100     using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements,
1101                                            FindInMap(typename Comp::InterfaceBindings, Type<NakedC>),
1102                                            HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>),
1103                                            Type<std::unique_ptr<NakedC>>, Type<std::unique_ptr<NakedC>(NakedArgs...)>,
1104                                            Id<RemoveAnnotations(Type<NakedArgs>)>...);
1105   };
1106 
1107   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename Annotation,
1108             typename NakedC, typename... NakedArgs>
1109   struct apply<Comp, TargetRequirements, TargetNonConstRequirements,
1110                Type<fruit::Annotated<Annotation, std::function<NakedC(NakedArgs...)>>>> {
1111     using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements,
1112                                            FindInMap(typename Comp::InterfaceBindings,
1113                                                      Type<fruit::Annotated<Annotation, NakedC>>),
1114                                            HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>), Type<NakedC>,
1115                                            Type<fruit::Annotated<Annotation, NakedC>(NakedArgs...)>,
1116                                            Id<RemoveAnnotations(Type<NakedArgs>)>...);
1117   };
1118 
1119   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename Annotation,
1120             typename NakedC, typename... NakedArgs>
1121   struct apply<Comp, TargetRequirements, TargetNonConstRequirements,
1122                Type<fruit::Annotated<Annotation, std::function<std::unique_ptr<NakedC>(NakedArgs...)>>>> {
1123     using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements,
1124                                            FindInMap(typename Comp::InterfaceBindings,
1125                                                      Type<fruit::Annotated<Annotation, NakedC>>),
1126                                            HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>),
1127                                            Type<std::unique_ptr<NakedC>>,
1128                                            Type<fruit::Annotated<Annotation, std::unique_ptr<NakedC>>(NakedArgs...)>,
1129                                            Id<RemoveAnnotations(Type<NakedArgs>)>...);
1130   };
1131 };
1132 
1133 template <typename AnnotatedT>
1134 struct EnsureProvidedTypeErrorHandler {
1135   template <typename E>
1136   struct apply {
1137     using type = E;
1138   };
1139 
1140   template <typename T>
1141   struct apply<Error<NoBindingFoundErrorTag, T>> {
1142     using type = If(IsSame(Type<T>, AnnotatedT),
1143                     ConstructError(ConstBindingDeclaredAsRequiredButNonConstBindingRequiredErrorTag, AnnotatedT),
1144                     ConstructError(NoBindingFoundErrorTag, Type<T>));
1145   };
1146 
1147   template <typename T1, typename T2>
1148   struct apply<Error<NoBindingFoundForAbstractClassErrorTag, T1, T2>> {
1149     using type = If(IsSame(Type<T1>, AnnotatedT),
1150                     ConstructError(ConstBindingDeclaredAsRequiredButNonConstBindingRequiredErrorTag, AnnotatedT),
1151                     ConstructError(NoBindingFoundForAbstractClassErrorTag, Type<T1>, Type<T2>));
1152   };
1153 };
1154 
1155 struct EnsureProvidedType {
1156   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedT,
1157             typename NonConstBindingRequired>
1158   struct apply {
1159     using AnnotatedC = NormalizeType(AnnotatedT);
1160     using AnnotatedCImpl = FindInMap(typename Comp::InterfaceBindings, AnnotatedC);
1161     using AutoRegisterResult = AutoRegister(Comp, TargetRequirements, TargetNonConstRequirements, AnnotatedC);
1162     using ErrorHandler = EnsureProvidedTypeErrorHandler<AnnotatedT>;
1163     using type = If(
1164         IsInSet(AnnotatedC, typename Comp::Ps),
1165         If(And(NonConstBindingRequired, Not(IsInSet(AnnotatedC, typename Comp::NonConstRsPs))),
1166            ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag, AnnotatedC),
1167            ComponentFunctorIdentity(Comp)),
1168         If(And(IsInSet(AnnotatedC, TargetRequirements),
1169                Or(Not(NonConstBindingRequired), IsInSet(AnnotatedC, TargetNonConstRequirements))),
1170            // The type is already in the target requirements with the desired constness, nothing to do.
1171            ComponentFunctorIdentity(Comp),
1172            If(Not(IsNone(AnnotatedCImpl)),
1173               // Has an interface binding.
1174               Call(ComposeFunctors(ComponentFunctor(ProcessInterfaceBinding, AnnotatedC, AnnotatedCImpl,
1175                                                     NonConstBindingRequired),
1176                                    ComponentFunctor(EnsureProvidedType, TargetRequirements, TargetNonConstRequirements,
1177                                                     AnnotatedCImpl, NonConstBindingRequired)),
1178                    Comp),
1179               // If we are about to report a NoBindingFound/NoBindingFoundForAbstractClass error for AnnotatedT and the
1180               // target
1181               // component has a Required<const T>, we can report a more specific error (rather than the usual
1182               // "binding not found").
1183               If(And(NonConstBindingRequired, IsInSet(AnnotatedC, TargetRequirements)),
1184                  Catch(Catch(AutoRegisterResult, NoBindingFoundErrorTag, ErrorHandler),
1185                        NoBindingFoundForAbstractClassErrorTag, ErrorHandler),
1186                  AutoRegisterResult))));
1187   };
1188 };
1189 
1190 struct EnsureProvidedTypes {
1191   template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename TypesToProvide,
1192             typename NonConstTypesToProvide>
1193   struct apply {
1194     struct Helper {
1195       template <typename CurrentResult, typename T>
1196       struct apply {
1197         using type = Compose2ComponentFunctors(ComponentFunctor(EnsureProvidedType, TargetRequirements,
1198                                                                 TargetNonConstRequirements, T,
1199                                                                 IsInSet(T, NonConstTypesToProvide)),
1200                                                CurrentResult);
1201       };
1202     };
1203 
1204     using type = Call(FoldVector(TypesToProvide, Helper, ComponentFunctorIdentity), Comp);
1205   };
1206 };
1207 
1208 struct ProcessBinding {
1209   template <typename Binding>
1210   struct apply;
1211 
1212   template <typename I, typename C>
1213   struct apply<fruit::impl::Bind<I, C>> {
1214     using type = ComponentFunctor(AddDeferredInterfaceBinding, Type<I>, Type<C>);
1215   };
1216 
1217   template <typename Signature>
1218   struct apply<fruit::impl::RegisterConstructor<Signature>> {
1219     using type = ComponentFunctor(DeferredRegisterConstructor, Type<Signature>);
1220   };
1221 
1222   template <typename AnnotatedC, typename C>
1223   struct apply<fruit::impl::BindInstance<AnnotatedC, C>> {
1224     using type = ComponentFunctor(RegisterInstance, Type<AnnotatedC>, Type<C>, Bool<true>);
1225   };
1226 
1227   template <typename AnnotatedC, typename C>
1228   struct apply<fruit::impl::BindConstInstance<AnnotatedC, C>> {
1229     using type = ComponentFunctor(RegisterInstance, Type<AnnotatedC>, Type<C>, Bool<false>);
1230   };
1231 
1232   template <typename Lambda>
1233   struct apply<fruit::impl::RegisterProvider<Lambda>> {
1234     using type = ComponentFunctor(DeferredRegisterProvider, Type<Lambda>);
1235   };
1236 
1237   template <typename AnnotatedSignature, typename Lambda>
1238   struct apply<fruit::impl::RegisterProvider<AnnotatedSignature, Lambda>> {
1239     using type = ComponentFunctor(DeferredRegisterProviderWithAnnotations, Type<AnnotatedSignature>, Type<Lambda>);
1240   };
1241 
1242   template <typename AnnotatedC>
1243   struct apply<fruit::impl::AddInstanceMultibinding<AnnotatedC>> {
1244     using type = ComponentFunctorIdentity;
1245   };
1246 
1247   template <typename AnnotatedC>
1248   struct apply<fruit::impl::AddInstanceVectorMultibindings<AnnotatedC>> {
1249     using type = ComponentFunctorIdentity;
1250   };
1251 
1252   template <typename I, typename C>
1253   struct apply<fruit::impl::AddMultibinding<I, C>> {
1254     using type = ComponentFunctor(AddInterfaceMultibinding, Type<I>, Type<C>);
1255   };
1256 
1257   template <typename Lambda>
1258   struct apply<fruit::impl::AddMultibindingProvider<Lambda>> {
1259     using type = ComponentFunctor(RegisterMultibindingProvider, Type<Lambda>);
1260   };
1261 
1262   template <typename AnnotatedSignature, typename Lambda>
1263   struct apply<fruit::impl::AddMultibindingProvider<AnnotatedSignature, Lambda>> {
1264     using type = ComponentFunctor(RegisterMultibindingProviderWithAnnotations, Type<AnnotatedSignature>, Type<Lambda>);
1265   };
1266 
1267   template <typename DecoratedSignature, typename Lambda>
1268   struct apply<fruit::impl::RegisterFactory<DecoratedSignature, Lambda>> {
1269     using type = ComponentFunctor(RegisterFactory, Type<DecoratedSignature>, Type<Lambda>);
1270   };
1271 
1272   template <typename... Params, typename... Args>
1273   struct apply<fruit::impl::InstallComponent<fruit::Component<Params...>(Args...)>> {
1274     using type = ComponentFunctor(InstallComponentHelper, Type<Params>...);
1275   };
1276 
1277   template <typename... ComponentFunctions>
1278   struct apply<fruit::impl::InstallComponentFunctions<ComponentFunctions...>> {
1279     using type = ComponentFunctor(InstallComponentFunctions, Type<ComponentFunctions>...);
1280   };
1281 
1282   template <typename GetReplacedComponent, typename GetReplacementComponent>
1283   struct apply<fruit::impl::ReplaceComponent<GetReplacedComponent, GetReplacementComponent>> {
1284     using type = ComponentFunctorIdentity;
1285   };
1286 };
1287 
1288 } // namespace meta
1289 } // namespace impl
1290 } // namespace fruit
1291 
1292 #endif // FRUIT_COMPONENT_FUNCTORS_DEFN_H
1293