HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Android 10
|
10.0.0_r6
下载
查看原文件
收藏
根目录
external
google-fruit
include
fruit
impl
component_functors.defn.h
/* * Copyright 2014 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FRUIT_COMPONENT_FUNCTORS_DEFN_H #define FRUIT_COMPONENT_FUNCTORS_DEFN_H #include
#include
#include
#include
#include
/********************************************************************************************************************************* This file contains functors that take a Comp and return a struct Op with the form: struct { using Result = Comp1; void operator()(FixedSizeVector
& entries) {...} std::size_t numEntries() {...} } *********************************************************************************************************************************/ namespace fruit { namespace impl { namespace meta { struct GetResult { template
struct apply { using type = typename F::Result; }; }; // Call(ComponentFunctor(F, Args...), Comp) // is equivalent to: // F(Comp, Args...) struct ComponentFunctor { template
struct apply { struct type { template
struct apply { using type = F(Comp, Args...); }; }; }; }; struct ComponentFunctorIdentity { template
struct apply { struct type { using Result = Comp; void operator()(FixedSizeVector
&) {} std::size_t numEntries() { return 0; } }; }; }; struct Compose2ComponentFunctors { template
struct apply { struct type { template
struct apply { using Op1 = F1(Comp); using Op2 = F2(GetResult(Op1)); struct Op { using Result = Eval
; void operator()(FixedSizeVector
& entries) { Eval
()(entries); Eval
()(entries); } std::size_t numEntries() { return Eval
().numEntries() + Eval
().numEntries(); } }; using type = PropagateError(Op1, PropagateError(Op2, Op)); }; }; }; }; // ComposeFunctors(F1,..,Fn) returns a functor that executes F1,..,Fn in order (stopping at the // first Error). struct ComposeFunctors { template
struct apply { using type = Fold(Compose2ComponentFunctors, ComponentFunctorIdentity, Functors...); }; }; // ReverseComposeFunctors(T1, ..., Tn) is equivalent to ComposeFunctors(Tn, ..., T1), but it's more // efficient when all of the following must be evaluated: // ReverseComposeFunctors
// ReverseComposeFunctors
// ReverseComposeFunctors
// In that case, this implementation shares many more instantiations with previous invocations struct ReverseComposeFunctors { template
struct apply { using type = ComponentFunctorIdentity; }; template
struct apply
{ using type = Functor; }; template
struct apply
{ using type = Compose2ComponentFunctors(ReverseComposeFunctors(Functors...), Functor); }; }; struct EnsureProvidedType; struct EnsureProvidedTypes; // Doesn't actually bind in ComponentStorage. The binding is added later (if needed) using ProcessInterfaceBinding. struct AddDeferredInterfaceBinding { template
struct apply { using Comp1 = ConsComp(typename Comp::RsSuperset, typename Comp::Ps, typename Comp::NonConstRsPs, #if !FRUIT_NO_LOOP_CHECK typename Comp::Deps, #endif PushFront(typename Comp::InterfaceBindings, Pair
), typename Comp::DeferredBindingFunctors); struct Op { // Note that we do NOT call AddProvidedType here. We'll only know the right required type // when the binding will be used. using Result = Eval
; void operator()(FixedSizeVector
&) {} std::size_t numEntries() { return 0; } }; using I = RemoveAnnotations(AnnotatedI); using C = RemoveAnnotations(AnnotatedC); using type = If(IsSame(I, C), ConstructError(InterfaceBindingToSelfErrorTag, C), If(Not(IsBaseOf(I, C)), ConstructError(NotABaseClassOfErrorTag, I, C), If(Not(IsSame(I, NormalizeType(I))), ConstructError(NonClassTypeErrorTag, I, NormalizeUntilStable(I)), If(Not(IsSame(C, NormalizeType(C))), // We handle this case too, just to be on the safe side, but this should never happen. ConstructError(NonClassTypeErrorTag, C, NormalizeUntilStable(C)), If(IsInSet(AnnotatedI, typename Comp::Ps), ConstructError(TypeAlreadyBoundErrorTag, AnnotatedI), If(MapContainsKey(typename Comp::InterfaceBindings, AnnotatedI), ConstructError(TypeAlreadyBoundErrorTag, AnnotatedI), Op)))))); }; }; struct ProcessInterfaceBinding { template
struct apply { using R = If(NonConstBindingRequired, AddProvidedTypeIgnoringInterfaceBindings(Comp, AnnotatedI, NonConstBindingRequired, Vector
, Vector
), AddProvidedTypeIgnoringInterfaceBindings(Comp, AnnotatedI, NonConstBindingRequired, Vector
, Vector<>)); struct ConstOp { // This must be here (and not in AddDeferredInterfaceBinding) because the binding might be // used to bind functors instead, so we might never need to add C to the requirements. using Result = Eval
; void operator()(FixedSizeVector
& entries) { entries.push_back( InjectorStorage::createComponentStorageEntryForConstBind
, UnwrapType
>()); }; std::size_t numEntries() { return 1; } }; struct NonConstOp { // This must be here (and not in AddDeferredInterfaceBinding) because the binding might be // used to bind functors instead, so we might never need to add C to the requirements. using Result = Eval
; void operator()(FixedSizeVector
& entries) { entries.push_back( InjectorStorage::createComponentStorageEntryForBind
, UnwrapType
>()); }; std::size_t numEntries() { return 1; } }; using type = PropagateError(R, If(NonConstBindingRequired, NonConstOp, ConstOp)); }; }; struct AddInterfaceMultibinding { template
struct apply { using I = RemoveAnnotations(AnnotatedI); using C = RemoveAnnotations(AnnotatedC); using R = AddRequirements(Comp, Vector
, Vector
); struct Op { using Result = Eval
; void operator()(FixedSizeVector
& entries) { entries.push_back(InjectorStorage::createComponentStorageEntryForMultibinding
, UnwrapType
>()); entries.push_back( InjectorStorage::createComponentStorageEntryForMultibindingVectorCreator
>()); }; std::size_t numEntries() { return 2; } }; using type = If(Not(IsBaseOf(I, C)), ConstructError(NotABaseClassOfErrorTag, I, C), Op); }; }; template
struct PostProcessRegisterProviderHelper; template
struct PostProcessRegisterProviderHelper; template
struct PostProcessRegisterProviderHelper
> { inline void operator()(FixedSizeVector
& entries) { entries.push_back( InjectorStorage::createComponentStorageEntryForCompressedProvider
()); entries.push_back(InjectorStorage::createComponentStorageEntryForProvider
()); } std::size_t numEntries() { return 2; } }; template
struct PostProcessRegisterProviderHelper
{ inline void operator()(FixedSizeVector
& entries) { entries.push_back(InjectorStorage::createComponentStorageEntryForProvider
()); } std::size_t numEntries() { return 1; } }; // T can't be any injectable type, it must match the return type of the provider in one of // the registerProvider() overloads in ComponentStorage. struct PostProcessRegisterProvider { template
struct apply { using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature)); using OptionalAnnotatedI = FindValueInMap(typename Comp::InterfaceBindings, AnnotatedC); struct Op { using Result = Comp; using Helper = PostProcessRegisterProviderHelper
, UnwrapType
, Eval
>; void operator()(FixedSizeVector
& entries) { Helper()(entries); } std::size_t numEntries() { return Helper().numEntries(); } }; using type = Op; }; }; struct PreProcessRegisterProvider { template
struct apply { using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature); using SignatureFromLambda = FunctionSignature(Lambda); using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature)); using AnnotatedCDeps = NormalizeTypeVector(SignatureArgs(AnnotatedSignature)); using R = AddProvidedType(Comp, AnnotatedC, Bool
, AnnotatedCDeps, Id
); using type = If(Not(IsSame(Signature, SignatureFromLambda)), ConstructError(AnnotatedSignatureDifferentFromLambdaSignatureErrorTag, Signature, SignatureFromLambda), PropagateError( CheckInjectableType(RemoveAnnotations(SignatureType(AnnotatedSignature))), PropagateError( CheckInjectableTypeVector(RemoveAnnotationsFromVector(AnnotatedCDeps)), PropagateError( CheckInjectableType(SignatureType(SignatureFromLambda)), PropagateError( CheckInjectableTypeVector(SignatureArgs(SignatureFromLambda)), If(And(IsPointer(SignatureType(SignatureFromLambda)), And(IsAbstract(RemovePointer(SignatureType(SignatureFromLambda))), Not(HasVirtualDestructor(RemovePointer(SignatureType(SignatureFromLambda)))))), ConstructError(ProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag, RemovePointer(SignatureType(SignatureFromLambda))), ComponentFunctorIdentity(R))))))); }; }; // The registration is actually deferred until the PartialComponent is converted to a component. struct DeferredRegisterProviderWithAnnotations { template
struct apply { using Comp1 = AddDeferredBinding(Comp, ComponentFunctor(PostProcessRegisterProvider, AnnotatedSignature, Lambda)); using type = PreProcessRegisterProvider(Comp1, AnnotatedSignature, Lambda); }; }; // The registration is actually deferred until the PartialComponent is converted to a component. struct DeferredRegisterProvider { template
struct apply { using type = DeferredRegisterProviderWithAnnotations(Comp, FunctionSignature(Lambda), Lambda); }; }; // T can't be any injectable type, it must match the return type of the provider in one of // the registerMultibindingProvider() overloads in ComponentStorage. struct RegisterMultibindingProviderWithAnnotations { template
struct apply { using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature); using SignatureFromLambda = FunctionSignature(Lambda); using AnnotatedArgs = SignatureArgs(AnnotatedSignature); using AnnotatedArgVector = NormalizeTypeVector(AnnotatedArgs); using NonConstRequirements = NormalizedNonConstTypesIn(AnnotatedArgs); using R = AddRequirements(Comp, AnnotatedArgVector, NonConstRequirements); struct Op { using Result = Eval
; void operator()(FixedSizeVector
& entries) { entries.push_back( InjectorStorage::createComponentStorageEntryForMultibindingProvider
, UnwrapType
>()); entries.push_back(InjectorStorage::createComponentStorageEntryForMultibindingVectorCreator< UnwrapType
>>()); } std::size_t numEntries() { return 2; } }; using type = If( Not(IsValidSignature(AnnotatedSignature)), ConstructError(NotASignatureErrorTag, AnnotatedSignature), PropagateError( CheckInjectableType(RemoveAnnotations(SignatureType(AnnotatedSignature))), PropagateError( CheckInjectableTypeVector(RemoveAnnotationsFromVector(SignatureArgs(AnnotatedSignature))), PropagateError( CheckInjectableType(SignatureType(SignatureFromLambda)), PropagateError( CheckInjectableTypeVector(SignatureArgs(SignatureFromLambda)), If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))), ConstructError(CannotConstructAbstractClassErrorTag, RemoveAnnotations(SignatureType(AnnotatedSignature))), If(Not(IsSame(Signature, SignatureFromLambda)), ConstructError(AnnotatedSignatureDifferentFromLambdaSignatureErrorTag, Signature, SignatureFromLambda), If(And(IsPointer(SignatureType(SignatureFromLambda)), And(IsAbstract(RemovePointer(SignatureType(SignatureFromLambda))), Not(HasVirtualDestructor(RemovePointer(SignatureType(SignatureFromLambda)))))), ConstructError( MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag, RemovePointer(SignatureType(SignatureFromLambda))), PropagateError(R, Op))))))))); }; }; // T can't be any injectable type, it must match the return type of the provider in one of // the registerMultibindingProvider() overloads in ComponentStorage. struct RegisterMultibindingProvider { template
struct apply { using type = RegisterMultibindingProviderWithAnnotations(Comp, FunctionSignature(Lambda), Lambda); }; }; // Non-assisted case. template
struct GetAssistedArg { template
inline Arg operator()(InjectedArgsTuple& injected_args, UserProvidedArgsTuple&) { return std::get
(injected_args); } }; // Assisted case. template
struct GetAssistedArg
> { template
inline Arg operator()(InjectedArgsTuple&, UserProvidedArgsTuple& user_provided_args) { return std::get
(user_provided_args); } }; struct RegisterFactoryHelper { template
is the injected type (possibly with an Annotation<> wrapping it) typename InjectedSignature, typename RequiredLambdaSignature, typename InjectedAnnotatedArgs, // The types that are injected, unwrapped from any Annotation<>. typename InjectedArgs, typename IndexSequence> struct apply; template
struct apply
, Type
, Vector
, Vector
...>, Vector
> { // Here we call "decorated" the types that might be wrapped in Annotated<> or Assisted<>, // while we call "annotated" the ones that might only be wrapped in Annotated<> (but not Assisted<>). using AnnotatedT = SignatureType(DecoratedSignature); using T = RemoveAnnotations(AnnotatedT); using DecoratedArgs = SignatureArgs(DecoratedSignature); using NakedInjectedSignature = NakedC(NakedUserProvidedArgs...); using NakedRequiredSignature = NakedC(NakedAllArgs...); using NakedFunctor = std::function
; // This is usually the same as Functor, but this might be annotated. using AnnotatedFunctor = CopyAnnotation(AnnotatedT, Type
); using FunctorDeps = NormalizeTypeVector(Vector
); using FunctorNonConstDeps = NormalizedNonConstTypesIn(Vector
); using R = AddProvidedType(Comp, AnnotatedFunctor, Bool
, FunctorDeps, FunctorNonConstDeps); struct Op { using Result = Eval
; void operator()(FixedSizeVector
& entries) { auto function_provider = [](NakedInjectedArgs... args) { auto injected_args = std::make_tuple(args...); auto object_provider = [injected_args](NakedUserProvidedArgs... params) mutable { auto user_provided_args = std::tie(params...); // These are unused if they are 0-arg tuples. Silence the unused-variable warnings anyway. (void)injected_args; (void)user_provided_args; return LambdaInvoker::invoke
, NakedAllArgs...>( GetAssistedArg< Eval
::value, getIntValue
() - Eval
::value, // Note that the Assisted<> wrapper (if any) remains, we just remove any wrapping Annotated<>. UnwrapType
>>()(injected_args, user_provided_args)...); }; return NakedFunctor(object_provider); }; entries.push_back(InjectorStorage::createComponentStorageEntryForProvider< UnwrapType
)>>, decltype(function_provider)>()); } std::size_t numEntries() { return 1; } }; // The first two IsValidSignature checks are a bit of a hack, they are needed to make the F2/RealF2 split // work in the caller (we need to allow Lambda to be a function type). using type = If(Not(IsSame(Type
, FunctionSignature(Lambda))), ConstructError(FunctorSignatureDoesNotMatchErrorTag, Type
, FunctionSignature(Lambda)), If(IsPointer(T), ConstructError(FactoryReturningPointerErrorTag, DecoratedSignature), PropagateError(R, Op))); }; }; struct RegisterFactory { template
struct apply { using LambdaReturnType = SignatureType(FunctionSignature(Lambda)); using type = If(Not(IsValidSignature(DecoratedSignature)), ConstructError(NotASignatureErrorTag, DecoratedSignature), PropagateError( CheckInjectableType(RemoveAnnotations(SignatureType(DecoratedSignature))), PropagateError( CheckInjectableTypeVector( RemoveAnnotationsFromVector(RemoveAssisted(SignatureArgs(DecoratedSignature)))), If(IsAbstract(RemoveAnnotations(SignatureType(DecoratedSignature))), // We error out early in this case. Calling RegisterFactoryHelper would also produce an error, but // it'd be // much less user-friendly. ConstructError(CannotConstructAbstractClassErrorTag, RemoveAnnotations(SignatureType(DecoratedSignature))), If(Not(Or(IsEmpty(Lambda), IsValidSignature(Lambda))), ConstructError(LambdaWithCapturesErrorTag, Lambda), If(Not(Or(IsTriviallyCopyable(Lambda), IsValidSignature(Lambda))), ConstructError(NonTriviallyCopyableLambdaErrorTag, Lambda), If(And(IsUniquePtr(LambdaReturnType), And(IsAbstract(RemoveUniquePtr(LambdaReturnType)), Not(HasVirtualDestructor(RemoveUniquePtr(LambdaReturnType))))), ConstructError(RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorErrorTag, RemoveUniquePtr(LambdaReturnType)), RegisterFactoryHelper( Comp, DecoratedSignature, Lambda, InjectedSignatureForAssistedFactory(DecoratedSignature), RequiredLambdaSignatureForAssistedFactory(DecoratedSignature), RemoveAssisted(SignatureArgs(DecoratedSignature)), RemoveAnnotationsFromVector(RemoveAssisted(SignatureArgs(DecoratedSignature))), GenerateIntSequence( VectorSize(RequiredLambdaArgsForAssistedFactory(DecoratedSignature))))))))))); }; }; struct PostProcessRegisterConstructor; template
struct PostProcessRegisterConstructorHelper; template
struct PostProcessRegisterConstructorHelper; template
struct PostProcessRegisterConstructorHelper
> { inline void operator()(FixedSizeVector
& entries) { entries.push_back( InjectorStorage::createComponentStorageEntryForCompressedConstructor
()); entries.push_back(InjectorStorage::createComponentStorageEntryForConstructor
()); } std::size_t numEntries() { return 2; } }; template
struct PostProcessRegisterConstructorHelper
{ inline void operator()(FixedSizeVector
& entries) { entries.push_back(InjectorStorage::createComponentStorageEntryForConstructor
()); } std::size_t numEntries() { return 1; } }; struct PostProcessRegisterConstructor { template
struct apply { struct type { using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature)); using Result = Comp; using Helper = PostProcessRegisterConstructorHelper
, Eval
>; void operator()(FixedSizeVector
& entries) { Helper()(entries); } std::size_t numEntries() { return Helper().numEntries(); } }; }; }; struct PreProcessRegisterConstructor { template
struct apply { using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature); using C = SignatureType(Signature); using Args = SignatureArgs(Signature); using AnnotatedT = SignatureType(AnnotatedSignature); using AnnotatedArgs = SignatureArgs(AnnotatedSignature); using AnnotatedC = NormalizeType(AnnotatedT); using CDeps = NormalizeTypeVector(AnnotatedArgs); using CNonConstDeps = NormalizedNonConstTypesIn(AnnotatedArgs); using R = AddProvidedType(Comp, AnnotatedC, Bool
, CDeps, CNonConstDeps); using type = If( Not(IsValidSignature(AnnotatedSignature)), ConstructError(NotASignatureErrorTag, AnnotatedSignature), PropagateError(CheckInjectableType(RemoveAnnotations(C)), PropagateError(CheckInjectableTypeVector(RemoveAnnotationsFromVector(Args)), If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))), ConstructError(CannotConstructAbstractClassErrorTag, RemoveAnnotations(SignatureType(AnnotatedSignature))), If(Not(IsConstructibleWithVector(C, Args)), ConstructError(NoConstructorMatchingInjectSignatureErrorTag, C, Signature), PropagateError(R, ComponentFunctorIdentity(R))))))); }; }; struct DeferredRegisterConstructor { template
struct apply { using Comp1 = AddDeferredBinding(Comp, ComponentFunctor(PostProcessRegisterConstructor, AnnotatedSignature)); using type = PreProcessRegisterConstructor(Comp1, AnnotatedSignature); }; }; struct RegisterInstance { template
struct apply { using R = AddProvidedType(Comp, AnnotatedC, IsNonConst, Vector<>, Vector<>); struct Op { using Result = Eval
; void operator()(FixedSizeVector
&) {} std::size_t numEntries() { return 0; } }; using type = PropagateError( CheckNormalizedTypes(ConsVector(RemoveAnnotations(AnnotatedC))), PropagateError( CheckNormalizedTypes(ConsVector(C)), If(Not(IsSame(C, NormalizeType(C))), ConstructError(NonClassTypeErrorTag, C, NormalizeUntilStable(C)), If(Not(IsSame(RemoveAnnotations(AnnotatedC), NormalizeType(RemoveAnnotations(AnnotatedC)))), ConstructError(NonClassTypeErrorTag, RemoveAnnotations(AnnotatedC), NormalizeUntilStable(RemoveAnnotations(C))), // The IsSame check is not redundant because IsBaseOf returns false for non-class types (e.g. int). If(Not(Or(IsSame(RemoveAnnotations(AnnotatedC), C), IsBaseOf(RemoveAnnotations(AnnotatedC), C))), ConstructError(TypeMismatchInBindInstanceErrorTag, RemoveAnnotations(AnnotatedC), C), PropagateError(R, Op)))))); }; }; struct RegisterConstructorAsValueFactory { template
> struct apply; template
struct apply
> { using RequiredSignature = Type
; using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature); struct Op { using Result = Eval
; void operator()(FixedSizeVector
& entries) { auto provider = [](NakedArgs... args) { return NakedT(std::forward
(args)...); }; using RealOp = RegisterFactory(Comp, DecoratedSignature, Type
); FruitStaticAssert(IsSame(GetResult(Op1), GetResult(RealOp))); Eval
()(entries); } std::size_t numEntries() { #if FRUIT_EXTRA_DEBUG auto provider = [](NakedArgs... args) { return NakedT(std::forward
(args)...); }; using RealOp = RegisterFactory(Comp, DecoratedSignature, Type
); FruitAssert(Eval
().numEntries() == Eval
().numEntries()); #endif return Eval
().numEntries(); } }; using type = PropagateError(Op1, Op); }; }; struct RegisterConstructorAsUniquePtrFactory { template
> struct apply; template
struct apply
(NakedArgs...)>> { using RequiredSignature = Type
(NakedArgs...)>; using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature); struct Op { using Result = Eval
; void operator()(FixedSizeVector
& entries) { auto provider = [](NakedArgs... args) { return std::unique_ptr
(new NakedT(std::forward
(args)...)); }; using RealOp = RegisterFactory(Comp, DecoratedSignature, Type
); FruitStaticAssert(IsSame(GetResult(Op1), GetResult(RealOp))); Eval
()(entries); }; std::size_t numEntries() { #if FRUIT_EXTRA_DEBUG auto provider = [](NakedArgs... args) { return std::unique_ptr
(new NakedT(std::forward
(args)...)); }; using RealOp = RegisterFactory(Comp, DecoratedSignature, Type
); FruitAssert(Eval
().numEntries() == Eval
().numEntries()); #endif return Eval
().numEntries(); } }; using type = PropagateError(Op1, Op); }; }; struct InstallComponent { template
struct apply { using new_RsSuperset = SetUnion(typename OtherComp::RsSuperset, typename Comp::RsSuperset); using new_Ps = SetUncheckedUnion(typename OtherComp::Ps, typename Comp::Ps); using new_NonConstRsPs = SetUnion(typename OtherComp::NonConstRsPs, typename Comp::NonConstRsPs); #if !FRUIT_NO_LOOP_CHECK using new_Deps = ConcatVectors(typename OtherComp::Deps, typename Comp::Deps); #endif FruitStaticAssert(IsSame(typename OtherComp::InterfaceBindings, Vector<>)); using new_InterfaceBindings = typename Comp::InterfaceBindings; FruitStaticAssert(IsSame(typename OtherComp::DeferredBindingFunctors, EmptyList)); using new_DeferredBindingFunctors = typename Comp::DeferredBindingFunctors; using R = ConsComp(new_RsSuperset, new_Ps, new_NonConstRsPs, #if !FRUIT_NO_LOOP_CHECK new_Deps, #endif new_InterfaceBindings, new_DeferredBindingFunctors); struct Op { using Result = Eval
; void operator()(FixedSizeVector
&) {} std::size_t numEntries() { return 0; } }; using InterfacePs = VectorToSetUnchecked(GetMapKeys(typename Comp::InterfaceBindings)); using AllPs = SetUncheckedUnion(InterfacePs, typename Comp::Ps); using DuplicateTypes = SetIntersection(typename OtherComp::Ps, AllPs); using CompConstPs = SetDifference(typename Comp::Ps, typename Comp::NonConstRsPs); using CompRs = SetDifference(typename Comp::RsSuperset, typename Comp::Ps); using CompNonConstRs = SetIntersection(CompRs, typename Comp::NonConstRsPs); using OtherCompConstPs = SetDifference(typename OtherComp::Ps, typename OtherComp::NonConstRsPs); using OtherCompRs = SetDifference(typename OtherComp::RsSuperset, typename OtherComp::Ps); using OtherCompNonConstRs = SetIntersection(OtherCompRs, typename OtherComp::NonConstRsPs); using type = If(Not(IsDisjoint(typename OtherComp::Ps, AllPs)), ConstructErrorWithArgVector(DuplicateTypesInComponentErrorTag, SetToVector(DuplicateTypes)), If(Not(IsDisjoint(CompConstPs, OtherCompNonConstRs)), ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag, GetArbitrarySetElement(SetIntersection(CompConstPs, OtherCompNonConstRs))), If(Not(IsDisjoint(CompNonConstRs, OtherCompConstPs)), ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag, GetArbitrarySetElement(SetIntersection(CompNonConstRs, OtherCompConstPs))), Op))); }; }; struct InstallComponentHelper { template
struct apply { using OtherComp = ConstructComponentImpl(OtherCompParams...); using type = InstallComponent(Comp, OtherComp); }; }; struct InstallComponentFunctions { template
struct apply; template
struct apply
{ using type = ComponentFunctorIdentity(Comp); }; template
struct apply
, ComponentFunctionArgs...>>, ComponentFunctions...> { using type = Call( Compose2ComponentFunctors( ComponentFunctor(InstallComponent, ConstructComponentImpl(Type
...)), ComponentFunctor(InstallComponentFunctions, ComponentFunctions...)), Comp); }; template
struct apply
{ using type = ConstructError(IncorrectArgTypePassedToInstallComponentFuntionsErrorTag, T); }; }; // CatchAll(PropagateError(Expr, Bool
), IsErrorExceptionHandler) evaluates to Bool
if Expr throws an error, // and Bool
otherwise. struct IsErrorExceptionHandler { template
struct apply { using type = Bool
; }; }; struct ConvertComponent { template
struct apply { using SourcePs = typename SourceComp::Ps; using DestPs = typename DestComp::Ps; using SourceRs = SetDifference(typename SourceComp::RsSuperset, typename SourceComp::Ps); using DestRs = SetDifference(typename DestComp::RsSuperset, typename DestComp::Ps); using NonConstSourceRs = SetIntersection(SourceRs, typename SourceComp::NonConstRsPs); using NonConstDestPs = SetIntersection(DestPs, typename DestComp::NonConstRsPs); using NonConstDestRs = SetIntersection(DestRs, typename DestComp::NonConstRsPs); using ConstSourcePs = SetDifference(SourcePs, typename SourceComp::NonConstRsPs); using ConstDestRs = SetDifference(DestRs, typename DestComp::NonConstRsPs); // We need to register: // * All the types provided by the new component // * All the types required by the old component // except: // * The ones already provided by the old component (if they have the right constness). // * The ones required by the new one (if they have the right constness). using ToRegister = SetUnion( // The types that we must provide and aren't currently provided SetDifference(SetUnion(DestPs, SourceRs), SetUnion(DestRs, SourcePs)), // And the ones that are currently provided as const but that we need to provide as non-const SetIntersection(SetUnion(NonConstDestPs, NonConstSourceRs), SetUnion(ConstDestRs, ConstSourcePs))); using NonConstTypesToRegister = SetIntersection(ToRegister, SetUnion(typename SourceComp::NonConstRsPs, typename DestComp::NonConstRsPs)); using type = EnsureProvidedTypes(SourceComp, DestRs, NonConstDestRs, SetToVector(ToRegister), NonConstTypesToRegister); // Not needed, just double-checking. // Uses FruitStaticAssert instead of FruitDelegateCheck so that it's checked only in debug mode. #if FRUIT_EXTRA_DEBUG FruitDelegateCheck( If(CatchAll(PropagateError(type, PropagateError(Id
, Bool
)), IsErrorExceptionHandler), // We're going to return an error soon anyway, we don't want to interfere by reporting this one. None, CheckComponentEntails(GetResult(type), DestComp))); #endif // FRUIT_EXTRA_DEBUG }; }; struct ProcessDeferredBindings { template
struct apply; template
struct apply
> { // Comp1 is the same as Comp, but without the DeferredBindingFunctors. using Comp1 = ConsComp(RsSupersetParam, PsParam, NonConstRsPsParam, #if !FRUIT_NO_LOOP_CHECK DepsParam, #endif InterfaceBindingsParam, EmptyList); using type = Call(FoldList(DeferredBindingFunctors, Compose2ComponentFunctors, ComponentFunctorIdentity), Comp1); }; }; template
struct AutoRegisterFactoryHelperErrorHandler { template
struct apply { using type = E; }; template
struct apply
> { using type = If(IsSame(Type
, AnnotatedCFunctor), ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor), ConstructError(NoBindingFoundErrorTag, Type
)); }; template
struct apply
> { using type = If(IsSame(Type
, AnnotatedCFunctor), ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor), ConstructError(NoBindingFoundForAbstractClassErrorTag, Type
, Type
)); }; }; struct AutoRegisterFactoryHelper { // General case, no way to bind it. template
struct apply { using AnnotatedC = SignatureType(AnnotatedSignature); using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature)); using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor); using type = If(IsAbstract(C), ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, C), ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor)); }; // No way to bind it (we need this specialization too to ensure that the specialization below // is not chosen for AnnotatedC=None). template
struct apply
>, AnnotatedSignature, Args...> { using AnnotatedC = SignatureType(AnnotatedSignature); using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature)); using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor); using type = If(IsAbstract(Type
), ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, Type
), ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor)); }; // AnnotatedI has an interface binding, use it and look for a factory that returns the type that AnnotatedI is bound // to. template
struct apply
>, AnnotatedSignature, Args...> { using I = Type
; using AnnotatedI = CopyAnnotation(SignatureType(AnnotatedSignature), I); using C = RemoveAnnotations(AnnotatedC); using IFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(I), Args...)); using CFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...)); using AnnotatedIFunctor = CopyAnnotation(AnnotatedI, IFunctor); using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor); using ProvidedSignature = ConsSignature(AnnotatedIFunctor, CopyAnnotation(AnnotatedC, ConsConstReference(CFunctor))); using LambdaSignature = ConsSignature(IFunctor, ConsConstReference(CFunctor)); using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, TargetNonConstRequirements, AnnotatedCFunctor, Bool
); using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature); using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature); using R = Call(ComposeFunctors(F1, F2, F3), Comp); struct Op { using Result = Eval
; void operator()(FixedSizeVector
& entries) { using NakedC = UnwrapType
>; auto provider = [](const UnwrapType
>& fun) { return UnwrapType
>([=](typename TypeUnwrapper
::type... args) { NakedC* c = fun(args...).release(); NakedI* i = static_cast
(c); return std::unique_ptr
(i); }); }; using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type
); using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type
); using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp); FruitStaticAssert(IsSame(GetResult(RealOp), GetResult(R))); Eval
()(entries); } std::size_t numEntries() { #if FRUIT_EXTRA_DEBUG using NakedC = UnwrapType
>; auto provider = [](const UnwrapType
>& fun) { return UnwrapType
>([=](typename TypeUnwrapper
::type... args) { NakedC* c = fun(args...).release(); NakedI* i = static_cast
(c); return std::unique_ptr
(i); }); }; using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type
); using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type
); using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp); FruitAssert(Eval
().numEntries() == Eval
().numEntries()); #endif return Eval
().numEntries(); } }; using type = PropagateError(R, If(Not(HasVirtualDestructor(I)), ConstructError(FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorErrorTag, IFunctor, CFunctor), Op)); }; // C doesn't have an interface binding as interface, nor an INJECT annotation, and is not an abstract class. // Bind std::function
(Args...)> to std::function
(possibly with annotations). template
struct apply
, Bool
, Type
>, AnnotatedSignature, Args...> { using C = Type
; using CFunctor = ConsStdFunction(ConsSignature(C, Args...)); using CUniquePtrFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...)); using AnnotatedCUniquePtr = SignatureType(AnnotatedSignature); using AnnotatedC = CopyAnnotation(AnnotatedCUniquePtr, C); using AnnotatedCFunctor = CopyAnnotation(AnnotatedCUniquePtr, CFunctor); using AnnotatedCUniquePtrFunctor = CopyAnnotation(AnnotatedCUniquePtr, CUniquePtrFunctor); using AnnotatedCFunctorRef = CopyAnnotation(AnnotatedCUniquePtr, ConsConstReference(CFunctor)); using ProvidedSignature = ConsSignature(AnnotatedCUniquePtrFunctor, AnnotatedCFunctorRef); using LambdaSignature = ConsSignature(CUniquePtrFunctor, ConsConstReference(CFunctor)); using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, TargetNonConstRequirements, AnnotatedCFunctor, Bool
); using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature); using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature); using R = Call(ComposeFunctors(F1, F2, F3), Comp); struct Op { using Result = Eval
; void operator()(FixedSizeVector
& entries) { auto provider = [](const UnwrapType
>& fun) { return UnwrapType
>([=](typename TypeUnwrapper
::type... args) { NakedC* c = new NakedC(fun(args...)); return std::unique_ptr
(c); }); }; using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type
); using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type
); using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp); FruitStaticAssert(IsSame(GetResult(RealOp), GetResult(R))); Eval
()(entries); } std::size_t numEntries() { #if FRUIT_EXTRA_DEBUG auto provider = [](const UnwrapType
>& fun) { return UnwrapType
>([=](typename TypeUnwrapper
::type... args) { NakedC* c = new NakedC(fun(args...)); return std::unique_ptr
(c); }); }; using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type
); using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type
); using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp); FruitAssert(Eval
().numEntries() == Eval
().numEntries()); #endif return Eval
().numEntries(); } }; using ErrorHandler = AutoRegisterFactoryHelperErrorHandler
, Eval