Home | History | Annotate | Download | only in impl
      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;
     68       void operator()(FixedSizeVector<ComponentStorageEntry>&) {}
     69       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)>;
     86           void operator()(FixedSizeVector<ComponentStorageEntry>& entries) {
     87             Eval<Op2>()(entries);
     88             Eval<Op1>()(entries);
     89           }
     90           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