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