HELLO·Android
系统源代码
IT资讯
技术文章
我的收藏
注册
登录
-
我收藏的文章
创建代码块
我的代码块
我的账号
Android 10
|
10.0.0_r6
下载
查看原文件
收藏
根目录
external
google-fruit
include
fruit
impl
meta
component.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_META_COMPONENT_H #define FRUIT_META_COMPONENT_H #include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
namespace fruit { namespace impl { namespace meta { //******************************************************************************************************************************** // Part 1: Simple type functors (no ConsComp involved). //******************************************************************************************************************************** // Given a type T, returns the class that should be injected to ensure that T is provided at runtime (if any). struct GetClassForType { // General case, if none of the following apply. // When adding a specialization here, make sure that the ComponentStorage // can actually get<> the specified type when the class was registered. template
struct apply; template
struct apply
> { using type = Type
; }; template
struct apply
> { using type = Type
; }; template
struct apply
> { using type = Type
; }; template
struct apply
> { using type = Type
; }; template
struct apply
> { using type = Type
; }; template
struct apply
> { using type = Type
; }; template
struct apply
>> { using type = Type
; }; template
struct apply
>> { using type = None; }; template
struct apply
>> { using type = Type
; }; template
struct apply
>> { using type = Type
; }; template
struct apply
>> { using type = Type
; }; }; struct GetClassForTypeVector { template
struct apply { using type = TransformVector(V, GetClassForType); }; }; // Given a type T, returns the type in the injection graph that corresponds to T. struct NormalizeType { // When adding a specialization here, make sure that the ComponentStorage // can actually get<> the specified type when the class was registered. template
struct apply; template
struct apply
> { using type = Type
; }; template
struct apply
> { using type = Type
; }; template
struct apply
> { using type = Type
; }; template
struct apply
> { using type = Type
; }; template
struct apply
> { using type = Type
; }; template
struct apply
> { using type = Type
; }; template
struct apply
>> { using type = Type
; }; template
struct apply
>> { using type = None; }; template
struct apply
>> { using type = Type
; }; template
struct apply
>> { using type = Type
; }; template
struct apply
>> { using type = Type
)>>>>; }; }; struct NormalizeUntilStable { template
struct apply { using type = If(IsSame(NormalizeType(T), T), T, NormalizeUntilStable(NormalizeType(T))); }; }; struct NormalizeTypeVector { template
struct apply { using type = TransformVector(V, NormalizeType); }; }; struct TypeInjectionRequiresNonConstBinding { template
struct apply; template
struct apply
> { using type = Bool
; }; template
struct apply
> { using type = Bool
; }; template
struct apply
> { using type = Bool
; }; template
struct apply
> { using type = Bool
; }; template
struct apply
> { using type = Bool
; }; template
struct apply
> { using type = Bool
; }; template
struct apply
>> { using type = Bool
; }; template
struct apply
>> { using type = Bool
; }; template
struct apply
>> { using type = Bool
; }; template
struct apply
>> { using type = Bool
; }; template
struct apply
>> { using type = TypeInjectionRequiresNonConstBinding(Type
); }; }; // Returns U wrapped in the same annotations in AnnotatedT (if any). struct CopyAnnotation { template
struct apply; template
struct apply { using type = U; }; template
struct apply
>, Type
> { using type = Type
>; }; }; struct IsValidSignature { template
struct apply { using type = Bool
; }; template
struct apply
> { using type = Bool
; }; }; // Removes the Annotation (if any) wrapping a type T. struct RemoveAnnotations { template
struct apply; template
struct apply
> { using type = Type
; }; template
struct apply
>> { using type = Type
; }; }; // Removes the Annotation(s) (if any) wrapping the types in AnnotatedSignature. struct RemoveAnnotationsFromSignature { template
struct apply { using type = ConstructError(NotASignatureErrorTag, AnnotatedSignature); }; template
struct apply
> { using type = ConsSignature(RemoveAnnotations(Type
), Id
)>...); }; }; // Removes the Annotation(s) (if any) wrapping the types in the Vector V. struct RemoveAnnotationsFromVector { template
struct apply { using type = TransformVector(V, RemoveAnnotations); }; }; // Maps T->T* in a possibly-annotated type. struct AddPointerInAnnotatedType { template
struct apply; template
struct apply
> { using type = Type
; }; template
struct apply
>> { using type = Type
>; }; }; // TODO: This also does UnlabelAssisted<>. Consider renaming and/or removing that logic (and // letting callers do the unlabeling when desired). struct RemoveNonAssisted { template
struct apply { struct Helper { // Non-assisted case template
struct apply { using type = CurrentResult; }; template
struct apply
>> { using type = PushBack(CurrentResult, Type
); }; }; using type = FoldVector(V, Helper, Vector<>); }; }; struct RemoveAssisted { template
struct apply { struct Helper { // Non-assisted case template
struct apply { using type = PushBack(CurrentResult, T); }; // Assisted case template
struct apply
>> { using type = CurrentResult; }; }; using type = FoldVector(V, Helper, Vector<>); }; }; struct UnlabelAssistedSingleType { template
struct apply; template
struct apply
> { using type = Type
; }; template
struct apply
>> { using type = Type
; }; }; struct UnlabelAssisted { template
struct apply { using type = TransformVector(V, UnlabelAssistedSingleType); }; }; struct RequiredLambdaArgsForAssistedFactory { template
struct apply { using type = RemoveAnnotationsFromVector(UnlabelAssisted(SignatureArgs(AnnotatedSignature))); }; }; struct RequiredLambdaSignatureForAssistedFactory { template
struct apply { using type = ConsSignatureWithVector(RemoveAnnotations(SignatureType(AnnotatedSignature)), RequiredLambdaArgsForAssistedFactory(AnnotatedSignature)); }; }; struct InjectedFunctionArgsForAssistedFactory { template
struct apply { using type = RemoveNonAssisted(SignatureArgs(AnnotatedSignature)); }; }; struct InjectedSignatureForAssistedFactory { template
struct apply { using type = ConsSignatureWithVector(RemoveAnnotations(SignatureType(AnnotatedSignature)), InjectedFunctionArgsForAssistedFactory(AnnotatedSignature)); }; }; struct IsAssisted { template
struct apply { using type = Bool
; }; template
struct apply
>> { using type = Bool
; }; }; struct NumAssisted { template
struct apply; template
struct apply
> { using type = SumAll(typename IsAssisted::apply
::type...); }; }; // Counts the number of Assisted<> types in V before the given index. struct NumAssistedBefore { template
struct apply; template
struct apply
, V> { using type = Int<0>; }; template
struct apply
, V> { using N = Int
; using type = Minus(NumAssisted(V), NumAssisted(VectorRemoveFirstN(V, N))); }; }; // Checks whether C is auto-injectable thanks to an Inject typedef. struct HasInjectAnnotation { template
struct apply; template
struct apply
> { template
static Bool
test(typename C1::Inject*); template
static Bool
test(...); using type = decltype(test
(nullptr)); }; }; struct DoGetInjectAnnotation { template
struct apply; template
struct apply
> { using type = Type
; }; }; struct GetInjectAnnotation { template
struct apply { using C = RemoveAnnotations(AnnotatedC); using DecoratedS = DoGetInjectAnnotation(C); using SResult = SignatureType(DecoratedS); using AnnotatedSArgs = SignatureArgs(DecoratedS); using SArgs = RemoveAnnotationsFromVector(UnlabelAssisted(AnnotatedSArgs)); // We replace the non-annotated return type with the potentially-annotated AnnotatedC. using AnnotatedDecoratedS = ConsSignatureWithVector(AnnotatedC, AnnotatedSArgs); using type = If(IsAbstract(C), ConstructError(CannotConstructAbstractClassErrorTag, C), If(Not(IsValidSignature(DecoratedS)), ConstructError(InjectTypedefNotASignatureErrorTag, C, DecoratedS), If(Not(IsSame(SResult, RemoveAnnotations(SResult))), ConstructError(InjectTypedefWithAnnotationErrorTag, C), If(Not(IsSame(C, SResult)), ConstructError(InjectTypedefForWrongClassErrorTag, C, SResult), If(Not(IsConstructibleWithVector(C, SArgs)), ConstructError(NoConstructorMatchingInjectSignatureErrorTag, C, ConsSignatureWithVector(SResult, SArgs)), AnnotatedDecoratedS))))); }; }; //******************************************************************************************************************************** // Part 2: Type functors involving at least one ConsComp. //******************************************************************************************************************************** template
struct Comp { // The actual set of requirements is SetDifference(RsSuperset, Ps) // We don't store Rs explicitly because we'd need to remove elements very often (and that's slow). using RsSuperset = RsSupersetParam; using Ps = PsParam; // This is a set of normalized types. // - If a type is in SetDifference(RsSuperset, Ps) and not here: it's required as const only // - If a type is in SetDifference(RsSuperset, Ps) and also here: it's required as non-const // - If a type is in Ps and not here: it's provided as const only // - If a type is in Ps and also here: it's provided as non-const using NonConstRsPs = NonConstRsPsParam; #if !FRUIT_NO_LOOP_CHECK using Deps = DepsParam; #endif using InterfaceBindings = InterfaceBindingsParam; using DeferredBindingFunctors = DeferredBindingFunctorsParam; // Invariants: // * all types appearing as arguments of Deps are in Rs // * all types in Ps are at the head of one (and only one) Dep. // (note that the types in Rs can appear in deps any number of times, 0 is also ok) // * Deps is of the form Vector
with each Dep of the form T(Args...) and where Vector
is a set (no // repetitions). // * Bindings is a proof tree forest, with injected classes as formulas. // * Each element X of the list DeferredBindingFunctors has: // - a default-constructible X::apply
type // - a void X::apply
::operator(ComponentStorage&) // - an X::apply
::Result type // * Each element of NonConstRsPs is in RsSuperset or in Ps (or both) }; // Using ConsComp instead of Comp<...> in a meta-expression allows the types to be evaluated. // See ConsVector for more details. struct ConsComp { template
struct apply { using type = Comp
; }; }; struct GetComponentDeps { template
struct apply { using type = typename Comp::Deps; }; }; struct GetComponentPs { template
struct apply { using type = typename Comp::Ps; }; }; struct GetComponentRsSuperset { template
struct apply { using type = typename Comp::RsSuperset; }; }; struct GetComponentNonConstRsPs { template
struct apply { using type = typename Comp::NonConstRsPs; }; }; struct IsInjectableBareType { template
struct apply; template
struct apply
> { using type = Bool
::value || std::is_class
::value || std::is_enum
::value>; }; template
struct apply
>> { using type = Bool
; }; template
struct apply
>> { using type = Bool
; }; }; // Checks if T is a (non-annotated) injectable type. struct IsInjectableType { template
struct apply { using type = IsInjectableBareType(NormalizeType(T)); }; }; // Checks that T is a (non-annotated) injectable type. If it isn't this returns an error, otherwise it returns None. struct CheckInjectableType { template
struct apply { using type = If(Not(IsInjectableType(T)), ConstructError(NonInjectableTypeErrorTag, T), None); }; }; // Checks that Types... are (non-annotated) injectable types. If they have an annotation or they are not injectable it // an appropriate error is returned. // Otherwise this returns None. struct CheckInjectableTypeVector { struct Helper { template
struct apply { using type = PropagateError(CheckInjectableType(T), CurrentResult); }; }; template
struct apply { using type = FoldVector(V, Helper, None); }; }; // Checks that Types... are normalized and injectable types. If not it returns an appropriate error. // If they are all normalized types this returns Result. struct CheckNormalizedTypes { template
struct apply; template
struct apply
...>> { struct Helper { template
struct apply { using NormalizedType = NormalizeType(T); using type = PropagateError(CheckInjectableType(RemoveAnnotations(NormalizeUntilStable(T))), If(Not(IsSame(NormalizeType(T), T)), ConstructError(NonClassTypeErrorTag, RemoveAnnotations(T), RemoveAnnotations(NormalizeUntilStable(T))), CurrentResult)); }; }; using type = Fold(Helper, None, Type
...); }; }; // Checks that Types... are not annotated types. If they have an annotation it returns an appropriate error. // If none of them is annotated, this returns None. struct CheckNotAnnotatedTypes { template
struct apply; template
struct apply
...>> { struct Helper { template
struct apply { using TypeWithoutAnnotations = RemoveAnnotations(T); using type = If(Not(IsSame(TypeWithoutAnnotations, T)), ConstructError(AnnotatedTypeErrorTag, T, TypeWithoutAnnotations), CurrentResult); }; }; using type = Fold(Helper, None, Type
...); }; }; // Check that there are no fruit::Required<> types in Component/NormalizedComponent's arguments. // If there aren't any, this returns None. struct CheckNoRequiredTypesInComponentArguments { template
struct apply; template
struct apply
> { using type = None; }; template
struct apply
, OtherTypes...>> { using type = CheckNoRequiredTypesInComponentArguments(Vector
); }; template
struct apply
>, OtherTypes...>> { using type = ConstructError(RequiredTypesInComponentArgumentsErrorTag, Type
>); }; }; // Check that there are no fruit::Required<> types in Injector's arguments. // If there aren't any, this returns None. struct CheckNoRequiredTypesInInjectorArguments { template
struct apply { using type = None; }; template
struct apply
{ using type = CheckNoRequiredTypesInInjectorArguments(Types...); }; template
struct apply
>, Types...> { using type = ConstructError(InjectorWithRequirementsErrorTag, Type
...); }; }; // Checks that there are no repetitions in Types. If there are, it returns an appropriate error. // If there are no repetitions it returns None. struct CheckNoRepeatedTypes { template
struct apply; template
struct apply