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::forward<typename std::tuple_element<numAssistedBefore, UserProvidedArgsTuple>::type>(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 437 struct ObjectProvider { 438 std::tuple<NakedInjectedArgs...> injected_args; 439 440 explicit ObjectProvider(std::tuple<NakedInjectedArgs...>&& injected_args) : injected_args(std::move(injected_args)) {} 441 442 NakedC operator()(NakedUserProvidedArgs&&... params) { 443 auto user_provided_args = std::forward_as_tuple(std::forward<decltype(params)>(params)...); 444 // These are unused if they are 0-arg tuples. Silence the unused-variable warnings anyway. 445 (void)injected_args; 446 (void)user_provided_args; 447 448 return LambdaInvoker::invoke<UnwrapType<Lambda>, NakedAllArgs...>( 449 GetAssistedArg< 450 Eval<NumAssistedBefore(Indexes, DecoratedArgs)>::value, 451 getIntValue<Indexes>() - Eval<NumAssistedBefore(Indexes, DecoratedArgs)>::value, 452 // Note that the Assisted<> wrapper (if any) remains, we just remove any wrapping Annotated<>. 453 UnwrapType<Eval<RemoveAnnotations(GetNthType(Indexes, DecoratedArgs))>>>()(injected_args, 454 user_provided_args)...); 455 } 456 }; 457 458 struct Op { 459 using Result = Eval<R>; 460 void operator()(FixedSizeVector<ComponentStorageEntry>& entries) { 461 auto function_provider = [](NakedInjectedArgs... args) { 462 return NakedFunctor{ObjectProvider{std::tuple<NakedInjectedArgs...>{args...}}}; 463 }; 464 (void)function_provider; 465 entries.push_back(InjectorStorage::createComponentStorageEntryForProvider< 466 UnwrapType<Eval<ConsSignatureWithVector(AnnotatedFunctor, Vector<InjectedAnnotatedArgs...>)>>, 467 decltype(function_provider)>()); 468 } 469 std::size_t numEntries() { 470 return 1; 471 } 472 }; 473 // The first two IsValidSignature checks are a bit of a hack, they are needed to make the F2/RealF2 split 474 // work in the caller (we need to allow Lambda to be a function type). 475 using type = If(Not(IsSame(Type<NakedRequiredSignature>, FunctionSignature(Lambda))), 476 ConstructError(FunctorSignatureDoesNotMatchErrorTag, Type<NakedRequiredSignature>, 477 FunctionSignature(Lambda)), 478 If(IsPointer(T), ConstructError(FactoryReturningPointerErrorTag, DecoratedSignature), 479 PropagateError(R, Op))); 480 }; 481 }; 482 483 struct RegisterFactory { 484 template <typename Comp, typename DecoratedSignature, typename Lambda> 485 struct apply { 486 using LambdaReturnType = SignatureType(FunctionSignature(Lambda)); 487 using type = 488 If(Not(IsValidSignature(DecoratedSignature)), ConstructError(NotASignatureErrorTag, DecoratedSignature), 489 PropagateError( 490 CheckInjectableType(RemoveAnnotations(SignatureType(DecoratedSignature))), 491 PropagateError( 492 CheckInjectableTypeVector( 493 RemoveAnnotationsFromVector(RemoveAssisted(SignatureArgs(DecoratedSignature)))), 494 If(IsAbstract(RemoveAnnotations(SignatureType(DecoratedSignature))), 495 // We error out early in this case. Calling RegisterFactoryHelper would also produce an error, but 496 // it'd be 497 // much less user-friendly. 498 ConstructError(CannotConstructAbstractClassErrorTag, 499 RemoveAnnotations(SignatureType(DecoratedSignature))), 500 If(Not(Or(IsEmpty(Lambda), IsValidSignature(Lambda))), 501 ConstructError(LambdaWithCapturesErrorTag, Lambda), 502 If(Not(Or(IsTriviallyCopyable(Lambda), IsValidSignature(Lambda))), 503 ConstructError(NonTriviallyCopyableLambdaErrorTag, Lambda), 504 If(And(IsUniquePtr(LambdaReturnType), 505 And(IsAbstract(RemoveUniquePtr(LambdaReturnType)), 506 Not(HasVirtualDestructor(RemoveUniquePtr(LambdaReturnType))))), 507 ConstructError(RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorErrorTag, 508 RemoveUniquePtr(LambdaReturnType)), 509 RegisterFactoryHelper( 510 Comp, DecoratedSignature, Lambda, 511 InjectedSignatureForAssistedFactory(DecoratedSignature), 512 RequiredLambdaSignatureForAssistedFactory(DecoratedSignature), 513 RemoveAssisted(SignatureArgs(DecoratedSignature)), 514 RemoveAnnotationsFromVector(RemoveAssisted(SignatureArgs(DecoratedSignature))), 515 GenerateIntSequence( 516 VectorSize(RequiredLambdaArgsForAssistedFactory(DecoratedSignature))))))))))); 517 }; 518 }; 519 520 struct PostProcessRegisterConstructor; 521 522 template <typename AnnotatedSignature, typename OptionalAnnotatedI> 523 struct PostProcessRegisterConstructorHelper; 524 525 template <typename AnnotatedSignature, typename AnnotatedI> 526 struct PostProcessRegisterConstructorHelper; 527 528 template <typename AnnotatedSignature, typename AnnotatedI> 529 struct PostProcessRegisterConstructorHelper<AnnotatedSignature, Type<AnnotatedI>> { 530 inline void operator()(FixedSizeVector<ComponentStorageEntry>& entries) { 531 entries.push_back( 532 InjectorStorage::createComponentStorageEntryForCompressedConstructor<AnnotatedSignature, AnnotatedI>()); 533 entries.push_back(InjectorStorage::createComponentStorageEntryForConstructor<AnnotatedSignature>()); 534 } 535 std::size_t numEntries() { 536 return 2; 537 } 538 }; 539 540 template <typename AnnotatedSignature> 541 struct PostProcessRegisterConstructorHelper<AnnotatedSignature, None> { 542 inline void operator()(FixedSizeVector<ComponentStorageEntry>& entries) { 543 entries.push_back(InjectorStorage::createComponentStorageEntryForConstructor<AnnotatedSignature>()); 544 } 545 std::size_t numEntries() { 546 return 1; 547 } 548 }; 549 550 struct PostProcessRegisterConstructor { 551 template <typename Comp, typename AnnotatedSignature> 552 struct apply { 553 struct type { 554 using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature)); 555 using Result = Comp; 556 using Helper = 557 PostProcessRegisterConstructorHelper<UnwrapType<AnnotatedSignature>, 558 Eval<FindValueInMap(typename Comp::InterfaceBindings, AnnotatedC)>>; 559 void operator()(FixedSizeVector<ComponentStorageEntry>& entries) { 560 Helper()(entries); 561 } 562 std::size_t numEntries() { 563 return Helper().numEntries(); 564 } 565 }; 566 }; 567 }; 568 569 struct PreProcessRegisterConstructor { 570 template <typename Comp, typename AnnotatedSignature> 571 struct apply { 572 using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature); 573 using C = SignatureType(Signature); 574 using Args = SignatureArgs(Signature); 575 using AnnotatedT = SignatureType(AnnotatedSignature); 576 using AnnotatedArgs = SignatureArgs(AnnotatedSignature); 577 using AnnotatedC = NormalizeType(AnnotatedT); 578 using CDeps = NormalizeTypeVector(AnnotatedArgs); 579 using CNonConstDeps = NormalizedNonConstTypesIn(AnnotatedArgs); 580 using R = AddProvidedType(Comp, AnnotatedC, Bool<true>, CDeps, CNonConstDeps); 581 using type = If(Not(IsValidSignature(AnnotatedSignature)), ConstructError(NotASignatureErrorTag, AnnotatedSignature), 582 If(Not(IsSame(RemoveAssisted(Args), Args)), ConstructError(AssistedParamInRegisterConstructorSignatureErrorTag, AnnotatedSignature), 583 PropagateError(CheckInjectableType(RemoveAnnotations(C)), 584 PropagateError(CheckInjectableTypeVector(RemoveAnnotationsFromVector(Args)), 585 If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))), 586 ConstructError(CannotConstructAbstractClassErrorTag, 587 RemoveAnnotations(SignatureType(AnnotatedSignature))), 588 If(Not(IsConstructibleWithVector(C, Args)), 589 ConstructError(NoConstructorMatchingInjectSignatureErrorTag, C, Signature), 590 PropagateError(R, ComponentFunctorIdentity(R)))))))); 591 }; 592 }; 593 594 struct DeferredRegisterConstructor { 595 template <typename Comp, typename AnnotatedSignature> 596 struct apply { 597 using Comp1 = AddDeferredBinding(Comp, ComponentFunctor(PostProcessRegisterConstructor, AnnotatedSignature)); 598 using type = PreProcessRegisterConstructor(Comp1, AnnotatedSignature); 599 }; 600 }; 601 602 struct RegisterInstance { 603 template <typename Comp, typename AnnotatedC, typename C, typename IsNonConst> 604 struct apply { 605 using R = AddProvidedType(Comp, AnnotatedC, IsNonConst, Vector<>, Vector<>); 606 struct Op { 607 using Result = Eval<R>; 608 void operator()(FixedSizeVector<ComponentStorageEntry>&) {} 609 std::size_t numEntries() { 610 return 0; 611 } 612 }; 613 using type = PropagateError( 614 CheckNormalizedTypes(ConsVector(RemoveAnnotations(AnnotatedC))), 615 PropagateError( 616 CheckNormalizedTypes(ConsVector(C)), 617 If(Not(IsSame(C, NormalizeType(C))), ConstructError(NonClassTypeErrorTag, C, NormalizeUntilStable(C)), 618 If(Not(IsSame(RemoveAnnotations(AnnotatedC), NormalizeType(RemoveAnnotations(AnnotatedC)))), 619 ConstructError(NonClassTypeErrorTag, RemoveAnnotations(AnnotatedC), 620 NormalizeUntilStable(RemoveAnnotations(C))), 621 // The IsSame check is not redundant because IsBaseOf returns false for non-class types (e.g. int). 622 If(Not(Or(IsSame(RemoveAnnotations(AnnotatedC), C), IsBaseOf(RemoveAnnotations(AnnotatedC), C))), 623 ConstructError(TypeMismatchInBindInstanceErrorTag, RemoveAnnotations(AnnotatedC), C), 624 PropagateError(R, Op)))))); 625 }; 626 }; 627 628 struct RegisterConstructorAsValueFactory { 629 template <typename Comp, typename DecoratedSignature, 630 typename RequiredSignature = Eval<RequiredLambdaSignatureForAssistedFactory(DecoratedSignature)>> 631 struct apply; 632 633 template <typename Comp, typename DecoratedSignature, typename NakedT, typename... NakedArgs> 634 struct apply<Comp, DecoratedSignature, Type<NakedT(NakedArgs...)>> { 635 using RequiredSignature = Type<NakedT(NakedArgs...)>; 636 using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature); 637 struct Op { 638 using Result = Eval<GetResult(Op1)>; 639 void operator()(FixedSizeVector<ComponentStorageEntry>& entries) { 640 auto provider = [](NakedArgs... args) { return NakedT(std::forward<NakedArgs>(args)...); }; 641 using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>); 642 FruitStaticAssert(IsSame(GetResult(Op1), GetResult(RealOp))); 643 Eval<RealOp>()(entries); 644 } 645 std::size_t numEntries() { 646 #if FRUIT_EXTRA_DEBUG 647 auto provider = [](NakedArgs... args) { return NakedT(std::forward<NakedArgs>(args)...); }; 648 using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>); 649 FruitAssert(Eval<Op1>().numEntries() == Eval<RealOp>().numEntries()); 650 #endif 651 return Eval<Op1>().numEntries(); 652 } 653 }; 654 using type = PropagateError(Op1, Op); 655 }; 656 }; 657 658 struct RegisterConstructorAsUniquePtrFactory { 659 template <typename Comp, typename DecoratedSignature, 660 typename RequiredSignature = Eval<RequiredLambdaSignatureForAssistedFactory(DecoratedSignature)>> 661 struct apply; 662 663 template <typename Comp, typename DecoratedSignature, typename NakedT, typename... NakedArgs> 664 struct apply<Comp, DecoratedSignature, Type<std::unique_ptr<NakedT>(NakedArgs...)>> { 665 using RequiredSignature = Type<std::unique_ptr<NakedT>(NakedArgs...)>; 666 using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature); 667 struct Op { 668 using Result = Eval<GetResult(Op1)>; 669 void operator()(FixedSizeVector<ComponentStorageEntry>& entries) { 670 auto provider = [](NakedArgs... args) { 671 return std::unique_ptr<NakedT>(new NakedT(std::forward<NakedArgs>(args)...)); 672 }; 673 // Changed to typedef from a using declaration to workaround a bug in MSVC 2022. 674 typedef RegisterFactory RealOp(Comp, DecoratedSignature, Type<decltype(provider)>); 675 FruitStaticAssert(IsSame(GetResult(Op1), GetResult(RealOp))); 676 Eval<RealOp>()(entries); 677 }; 678 std::size_t numEntries() { 679 #if FRUIT_EXTRA_DEBUG 680 auto provider = [](NakedArgs... args) { 681 return std::unique_ptr<NakedT>(new NakedT(std::forward<NakedArgs>(args)...)); 682 }; 683 using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>); 684 FruitAssert(Eval<Op1>().numEntries() == Eval<RealOp>().numEntries()); 685 #endif 686 return Eval<Op1>().numEntries(); 687 } 688 }; 689 690 using type = PropagateError(Op1, Op); 691 }; 692 }; 693 694 struct InstallComponent { 695 template <typename Comp, typename OtherComp> 696 struct apply { 697 using new_RsSuperset = SetUnion(typename OtherComp::RsSuperset, typename Comp::RsSuperset); 698 using new_Ps = SetUncheckedUnion(typename OtherComp::Ps, typename Comp::Ps); 699 using new_NonConstRsPs = SetUnion(typename OtherComp::NonConstRsPs, typename Comp::NonConstRsPs); 700 #if !FRUIT_NO_LOOP_CHECK 701 using new_Deps = ConcatVectors(typename OtherComp::Deps, typename Comp::Deps); 702 #endif 703 FruitStaticAssert(IsSame(typename OtherComp::InterfaceBindings, Vector<>)); 704 using new_InterfaceBindings = typename Comp::InterfaceBindings; 705 706 FruitStaticAssert(IsSame(typename OtherComp::DeferredBindingFunctors, EmptyList)); 707 using new_DeferredBindingFunctors = typename Comp::DeferredBindingFunctors; 708 709 using R = ConsComp(new_RsSuperset, new_Ps, new_NonConstRsPs, 710 #if !FRUIT_NO_LOOP_CHECK 711 new_Deps, 712 #endif 713 new_InterfaceBindings, new_DeferredBindingFunctors); 714 struct Op { 715 using Result = Eval<R>; 716 void operator()(FixedSizeVector<ComponentStorageEntry>&) {} 717 std::size_t numEntries() { 718 return 0; 719 } 720 }; 721 using InterfacePs = VectorToSetUnchecked(GetMapKeys(typename Comp::InterfaceBindings)); 722 using AllPs = SetUncheckedUnion(InterfacePs, typename Comp::Ps); 723 using DuplicateTypes = SetIntersection(typename OtherComp::Ps, AllPs); 724 using CompConstPs = SetDifference(typename Comp::Ps, typename Comp::NonConstRsPs); 725 using CompRs = SetDifference(typename Comp::RsSuperset, typename Comp::Ps); 726 using CompNonConstRs = SetIntersection(CompRs, typename Comp::NonConstRsPs); 727 728 using OtherCompConstPs = SetDifference(typename OtherComp::Ps, typename OtherComp::NonConstRsPs); 729 using OtherCompRs = SetDifference(typename OtherComp::RsSuperset, typename OtherComp::Ps); 730 using OtherCompNonConstRs = SetIntersection(OtherCompRs, typename OtherComp::NonConstRsPs); 731 732 using type = If(Not(IsDisjoint(typename OtherComp::Ps, AllPs)), 733 ConstructErrorWithArgVector(DuplicateTypesInComponentErrorTag, SetToVector(DuplicateTypes)), 734 If(Not(IsDisjoint(CompConstPs, OtherCompNonConstRs)), 735 ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag, 736 GetArbitrarySetElement(SetIntersection(CompConstPs, OtherCompNonConstRs))), 737 If(Not(IsDisjoint(CompNonConstRs, OtherCompConstPs)), 738 ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag, 739 GetArbitrarySetElement(SetIntersection(CompNonConstRs, OtherCompConstPs))), 740 Op))); 741 }; 742 }; 743 744 struct InstallComponentHelper { 745 template <typename Comp, typename... OtherCompParams> 746 struct apply { 747 using OtherComp = ConstructComponentImpl(OtherCompParams...); 748 using type = InstallComponent(Comp, OtherComp); 749 }; 750 }; 751 752 struct InstallComponentFunctions { 753 template <typename Comp, typename... ComponentFunctions> 754 struct apply; 755 756 template <typename Comp> 757 struct apply<Comp> { 758 using type = ComponentFunctorIdentity(Comp); 759 }; 760 761 template <typename Comp, typename... ComponentParams, typename... ComponentFunctionArgs, typename... ComponentFunctions> 762 struct apply<Comp, Type<fruit::ComponentFunction<fruit::Component<ComponentParams...>, ComponentFunctionArgs...>>, ComponentFunctions...> { 763 using type = 764 Call( 765 Compose2ComponentFunctors( 766 ComponentFunctor(InstallComponent, ConstructComponentImpl(Type<ComponentParams>...)), 767 ComponentFunctor(InstallComponentFunctions, ComponentFunctions...)), 768 Comp); 769 }; 770 771 template <typename Comp, typename T, typename... ComponentFunctions> 772 struct apply<Comp, T, ComponentFunctions...> { 773 using type = ConstructError(IncorrectArgTypePassedToInstallComponentFuntionsErrorTag, T); 774 }; 775 }; 776 777 // CatchAll(PropagateError(Expr, Bool<false>), IsErrorExceptionHandler) evaluates to Bool<true> if Expr throws an error, 778 // and Bool<false> otherwise. 779 struct IsErrorExceptionHandler { 780 template <typename E> 781 struct apply { 782 using type = Bool<true>; 783 }; 784 }; 785 786 struct ConvertComponent { 787 template <typename SourceComp, typename DestComp> 788 struct apply { 789 using SourcePs = typename SourceComp::Ps; 790 using DestPs = typename DestComp::Ps; 791 using SourceRs = SetDifference(typename SourceComp::RsSuperset, typename SourceComp::Ps); 792 using DestRs = SetDifference(typename DestComp::RsSuperset, typename DestComp::Ps); 793 using NonConstSourceRs = SetIntersection(SourceRs, typename SourceComp::NonConstRsPs); 794 using NonConstDestPs = SetIntersection(DestPs, typename DestComp::NonConstRsPs); 795 using NonConstDestRs = SetIntersection(DestRs, typename DestComp::NonConstRsPs); 796 797 using ConstSourcePs = SetDifference(SourcePs, typename SourceComp::NonConstRsPs); 798 using ConstDestRs = SetDifference(DestRs, typename DestComp::NonConstRsPs); 799 800 // We need to register: 801 // * All the types provided by the new component 802 // * All the types required by the old component 803 // except: 804 // * The ones already provided by the old component (if they have the right constness). 805 // * The ones required by the new one (if they have the right constness). 806 using ToRegister = SetUnion( 807 // The types that we must provide and aren't currently provided 808 SetDifference(SetUnion(DestPs, SourceRs), SetUnion(DestRs, SourcePs)), 809 // And the ones that are currently provided as const but that we need to provide as non-const 810 SetIntersection(SetUnion(NonConstDestPs, NonConstSourceRs), SetUnion(ConstDestRs, ConstSourcePs))); 811 using NonConstTypesToRegister = SetIntersection(ToRegister, SetUnion(typename SourceComp::NonConstRsPs, 812 typename DestComp::NonConstRsPs)); 813 using type = EnsureProvidedTypes(SourceComp, DestRs, NonConstDestRs, SetToVector(ToRegister), 814 NonConstTypesToRegister); 815 816 // Not needed, just double-checking. 817 // Uses FruitStaticAssert instead of FruitDelegateCheck so that it's checked only in debug mode. 818 #if FRUIT_EXTRA_DEBUG 819 FruitDelegateCheck( 820 If(CatchAll(PropagateError(type, PropagateError(Id<GetResult(type)>, Bool<false>)), IsErrorExceptionHandler), 821 // We're going to return an error soon anyway, we don't want to interfere by reporting this one. 822 None, CheckComponentEntails(GetResult(type), DestComp))); 823 #endif // FRUIT_EXTRA_DEBUG 824 }; 825 }; 826 827 struct ProcessDeferredBindings { 828 template <typename Comp> 829 struct apply; 830 831 template <typename RsSupersetParam, typename PsParam, typename NonConstRsPsParam, 832 #if !FRUIT_NO_LOOP_CHECK 833 typename DepsParam, 834 #endif 835 typename InterfaceBindingsParam, typename DeferredBindingFunctors> 836 struct apply<Comp<RsSupersetParam, PsParam, NonConstRsPsParam, 837 #if !FRUIT_NO_LOOP_CHECK 838 DepsParam, 839 #endif 840 InterfaceBindingsParam, DeferredBindingFunctors>> { 841 // Comp1 is the same as Comp, but without the DeferredBindingFunctors. 842 using Comp1 = ConsComp(RsSupersetParam, PsParam, NonConstRsPsParam, 843 #if !FRUIT_NO_LOOP_CHECK 844 DepsParam, 845 #endif 846 InterfaceBindingsParam, EmptyList); 847 using type = Call(FoldList(DeferredBindingFunctors, Compose2ComponentFunctors, ComponentFunctorIdentity), Comp1); 848 }; 849 }; 850 851 template <typename AnnotatedCFunctor, typename AnnotatedCUniquePtrFunctor> 852 struct AutoRegisterFactoryHelperErrorHandler { 853 template <typename E> 854 struct apply { 855 using type = E; 856 }; 857 858 template <typename T> 859 struct apply<Error<NoBindingFoundErrorTag, T>> { 860 using type = If(IsSame(Type<T>, AnnotatedCFunctor), ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor), 861 ConstructError(NoBindingFoundErrorTag, Type<T>)); 862 }; 863 864 template <typename T1, typename T2> 865 struct apply<Error<NoBindingFoundForAbstractClassErrorTag, T1, T2>> { 866 using type = If(IsSame(Type<T1>, AnnotatedCFunctor), ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor), 867 ConstructError(NoBindingFoundForAbstractClassErrorTag, Type<T1>, Type<T2>)); 868 }; 869 }; 870 871 struct AutoRegisterFactoryHelper { 872 873 // General case, no way to bind it. 874 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename InterfaceBinding, 875 typename has_inject_annotation, typename is_abstract, typename C, typename AnnotatedSignature, 876 typename... Args> 877 struct apply { 878 using AnnotatedC = SignatureType(AnnotatedSignature); 879 using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature)); 880 using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor); 881 using type = If(IsAbstract(C), ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, C), 882 ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor)); 883 }; 884 885 // No way to bind it (we need this specialization too to ensure that the specialization below 886 // is not chosen for AnnotatedC=None). 887 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename unused1, 888 typename unused2, typename NakedI, typename AnnotatedSignature, typename... Args> 889 struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, unused1, unused2, 890 Type<std::unique_ptr<NakedI>>, AnnotatedSignature, Args...> { 891 using AnnotatedC = SignatureType(AnnotatedSignature); 892 using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature)); 893 using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor); 894 using type = If(IsAbstract(Type<NakedI>), 895 ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, Type<NakedI>), 896 ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor)); 897 }; 898 899 // AnnotatedI has an interface binding, use it and look for a factory that returns the type that AnnotatedI is bound 900 // to. 901 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedC, 902 typename unused1, typename unused2, typename NakedI, typename AnnotatedSignature, typename... Args> 903 struct apply<Comp, TargetRequirements, TargetNonConstRequirements, AnnotatedC, unused1, unused2, 904 Type<std::unique_ptr<NakedI>>, AnnotatedSignature, Args...> { 905 using I = Type<NakedI>; 906 using AnnotatedI = CopyAnnotation(SignatureType(AnnotatedSignature), I); 907 using C = RemoveAnnotations(AnnotatedC); 908 using IFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(I), Args...)); 909 using CFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...)); 910 using AnnotatedIFunctor = CopyAnnotation(AnnotatedI, IFunctor); 911 using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor); 912 913 using ProvidedSignature = ConsSignature(AnnotatedIFunctor, 914 CopyAnnotation(AnnotatedC, ConsConstReference(CFunctor))); 915 using LambdaSignature = ConsSignature(IFunctor, ConsConstReference(CFunctor)); 916 917 using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, TargetNonConstRequirements, AnnotatedCFunctor, 918 Bool<false>); 919 using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature); 920 using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature); 921 using R = Call(ComposeFunctors(F1, F2, F3), Comp); 922 struct Op { 923 using Result = Eval<GetResult(R)>; 924 using NakedC = UnwrapType<Eval<C>>; 925 void operator()(FixedSizeVector<ComponentStorageEntry>& entries) { 926 auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) { 927 return UnwrapType<Eval<IFunctor>>([=](typename Args::type... args) { 928 NakedC* c = fun(args...).release(); 929 NakedI* i = static_cast<NakedI*>(c); 930 return std::unique_ptr<NakedI>(i); 931 }); 932 }; 933 FruitStaticAssert(IsSame( 934 GetResult( 935 Call(ComposeFunctors( 936 F1, 937 ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>), 938 ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>)), 939 Comp)), 940 GetResult(R))); 941 Eval<Call(ComposeFunctors( 942 F1, 943 ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>), 944 ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>)), 945 Comp)>()(entries); 946 } 947 std::size_t numEntries() { 948 #if FRUIT_EXTRA_DEBUG 949 auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) { 950 return UnwrapType<Eval<IFunctor>>([=](typename Args::type... args) { 951 NakedC* c = fun(args...).release(); 952 NakedI* i = static_cast<NakedI*>(c); 953 return std::unique_ptr<NakedI>(i); 954 }); 955 }; 956 FruitAssert( 957 Eval<R>().numEntries() == 958 Eval<Call(ComposeFunctors( 959 F1, ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>), 960 ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>)), 961 Comp)>() 962 .numEntries()); 963 #endif 964 return Eval<R>().numEntries(); 965 } 966 }; 967 using type = PropagateError(R, If(Not(HasVirtualDestructor(I)), 968 ConstructError(FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorErrorTag, 969 IFunctor, CFunctor), 970 Op)); 971 }; 972 973 // C doesn't have an interface binding as interface, nor an INJECT annotation, and is not an abstract class. 974 // Bind std::function<unique_ptr<C>(Args...)> to std::function<C(Args...)> (possibly with annotations). 975 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename NakedC, 976 typename AnnotatedSignature, typename... Args> 977 struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, Bool<false>, Bool<false>, 978 Type<std::unique_ptr<NakedC>>, AnnotatedSignature, Args...> { 979 using C = Type<NakedC>; 980 using CFunctor = ConsStdFunction(ConsSignature(C, Args...)); 981 using CUniquePtrFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...)); 982 using AnnotatedCUniquePtr = SignatureType(AnnotatedSignature); 983 using AnnotatedC = CopyAnnotation(AnnotatedCUniquePtr, C); 984 using AnnotatedCFunctor = CopyAnnotation(AnnotatedCUniquePtr, CFunctor); 985 using AnnotatedCUniquePtrFunctor = CopyAnnotation(AnnotatedCUniquePtr, CUniquePtrFunctor); 986 using AnnotatedCFunctorRef = CopyAnnotation(AnnotatedCUniquePtr, ConsConstReference(CFunctor)); 987 988 using ProvidedSignature = ConsSignature(AnnotatedCUniquePtrFunctor, AnnotatedCFunctorRef); 989 using LambdaSignature = ConsSignature(CUniquePtrFunctor, ConsConstReference(CFunctor)); 990 991 using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, TargetNonConstRequirements, AnnotatedCFunctor, 992 Bool<false>); 993 using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature); 994 using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature); 995 using R = Call(ComposeFunctors(F1, F2, F3), Comp); 996 struct Op { 997 using Result = Eval<GetResult(R)>; 998 void operator()(FixedSizeVector<ComponentStorageEntry>& entries) { 999 auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) { 1000 return UnwrapType<Eval<CUniquePtrFunctor>>([=](typename TypeUnwrapper<Args>::type... args) { 1001 NakedC* c = new NakedC(fun(args...)); 1002 return std::unique_ptr<NakedC>(c); 1003 }); 1004 }; 1005 using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); 1006 using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); 1007 using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp); 1008 FruitStaticAssert(IsSame(GetResult(RealOp), GetResult(R))); 1009 Eval<RealOp>()(entries); 1010 } 1011 std::size_t numEntries() { 1012 #if FRUIT_EXTRA_DEBUG 1013 auto provider = [](const UnwrapType<Eval<CFunctor>>& fun) { 1014 return UnwrapType<Eval<CUniquePtrFunctor>>([=](typename TypeUnwrapper<Args>::type... args) { 1015 NakedC* c = new NakedC(fun(args...)); 1016 return std::unique_ptr<NakedC>(c); 1017 }); 1018 }; 1019 using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); 1020 using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); 1021 using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp); 1022 FruitAssert(Eval<R>().numEntries() == Eval<RealOp>().numEntries()); 1023 #endif 1024 return Eval<R>().numEntries(); 1025 } 1026 }; 1027 1028 using ErrorHandler = 1029 AutoRegisterFactoryHelperErrorHandler<Eval<AnnotatedCFunctor>, Eval<AnnotatedCUniquePtrFunctor>>; 1030 1031 // If we are about to report a NoBindingFound/NoBindingFoundForAbstractClass error for AnnotatedCFunctor, 1032 // report one for std::function<std::unique_ptr<C>(Args...)> instead, 1033 // otherwise we'd report an error about a type that the user doesn't expect. 1034 using type = PropagateError(Catch(Catch(R, NoBindingFoundErrorTag, ErrorHandler), 1035 NoBindingFoundForAbstractClassErrorTag, ErrorHandler), 1036 Op); 1037 }; 1038 1039 // C has an Inject typedef, use it. unique_ptr case. 1040 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename unused, 1041 typename NakedC, typename AnnotatedSignature, typename... Args> 1042 struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, Bool<true>, unused, 1043 Type<std::unique_ptr<NakedC>>, AnnotatedSignature, Args...> { 1044 using AnnotatedCUniquePtr = SignatureType(AnnotatedSignature); 1045 using AnnotatedC = CopyAnnotation(AnnotatedCUniquePtr, RemoveUniquePtr(RemoveAnnotations(AnnotatedCUniquePtr))); 1046 using DecoratedSignatureReturningValue = GetInjectAnnotation(AnnotatedC); 1047 using DecoratedSignature = ConsSignatureWithVector(AnnotatedCUniquePtr, 1048 SignatureArgs(DecoratedSignatureReturningValue)); 1049 using DecoratedSignatureArgs = SignatureArgs(DecoratedSignature); 1050 using ActualSignatureInInjectionTypedef = ConsSignatureWithVector(SignatureType(DecoratedSignature), 1051 RemoveNonAssisted(DecoratedSignatureArgs)); 1052 using NonAssistedArgs = RemoveAssisted(DecoratedSignatureArgs); 1053 1054 using F1 = ComponentFunctor(RegisterConstructorAsUniquePtrFactory, DecoratedSignature); 1055 using F2 = ComponentFunctor(EnsureProvidedTypes, TargetRequirements, TargetNonConstRequirements, 1056 NormalizeTypeVector(NonAssistedArgs), NormalizedNonConstTypesIn(NonAssistedArgs)); 1057 1058 using type = If(Not(IsSame(AnnotatedSignature, ActualSignatureInInjectionTypedef)), 1059 ConstructError(FunctorSignatureDoesNotMatchErrorTag, AnnotatedSignature, 1060 ActualSignatureInInjectionTypedef), 1061 Call(ComposeFunctors(F1, F2), Comp)); 1062 }; 1063 1064 // C has an Inject typedef, use it. Value (not unique_ptr) case. 1065 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename unused, 1066 typename NakedC, typename AnnotatedSignature, typename... Args> 1067 struct apply<Comp, TargetRequirements, TargetNonConstRequirements, None, Bool<true>, unused, Type<NakedC>, 1068 AnnotatedSignature, Args...> { 1069 using AnnotatedC = SignatureType(AnnotatedSignature); 1070 using DecoratedSignature = GetInjectAnnotation(AnnotatedC); 1071 using DecoratedSignatureArgs = SignatureArgs(DecoratedSignature); 1072 using ActualSignatureInInjectionTypedef = ConsSignatureWithVector(SignatureType(DecoratedSignature), 1073 RemoveNonAssisted(DecoratedSignatureArgs)); 1074 using NonAssistedArgs = RemoveAssisted(DecoratedSignatureArgs); 1075 1076 using F1 = ComponentFunctor(RegisterConstructorAsValueFactory, DecoratedSignature); 1077 using F2 = ComponentFunctor(EnsureProvidedTypes, TargetRequirements, TargetNonConstRequirements, 1078 NormalizeTypeVector(NonAssistedArgs), NormalizedNonConstTypesIn(NonAssistedArgs)); 1079 1080 using type = If(Not(IsSame(AnnotatedSignature, ActualSignatureInInjectionTypedef)), 1081 ConstructError(FunctorSignatureDoesNotMatchErrorTag, AnnotatedSignature, 1082 ActualSignatureInInjectionTypedef), 1083 Call(ComposeFunctors(F1, F2), Comp)); 1084 }; 1085 }; 1086 1087 struct AutoRegister { 1088 // The types in TargetRequirements will not be auto-registered. 1089 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedC> 1090 struct apply; 1091 1092 // Tries to register C by looking for a typedef called Inject inside C. 1093 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedC> 1094 struct apply { 1095 using CHasInjectAnnotation = HasInjectAnnotation(RemoveAnnotations(AnnotatedC)); 1096 using Inject = GetInjectAnnotation(AnnotatedC); 1097 using CRequirements = NormalizeTypeVector(SignatureArgs(Inject)); 1098 using CNonConstRequirements = NormalizedNonConstTypesIn(SignatureArgs(Inject)); 1099 using F = ComposeFunctors(ComponentFunctor(PreProcessRegisterConstructor, Inject), 1100 ComponentFunctor(PostProcessRegisterConstructor, Inject), 1101 ComponentFunctor(EnsureProvidedTypes, TargetRequirements, TargetNonConstRequirements, 1102 CRequirements, CNonConstRequirements)); 1103 using type = If(CHasInjectAnnotation, Call(F, Comp), ConstructNoBindingFoundError(AnnotatedC)); 1104 }; 1105 1106 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename NakedC, 1107 typename... NakedArgs> 1108 struct apply<Comp, TargetRequirements, TargetNonConstRequirements, Type<std::function<NakedC(NakedArgs...)>>> { 1109 using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements, 1110 FindInMap(typename Comp::InterfaceBindings, Type<NakedC>), 1111 HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>), Type<NakedC>, 1112 Type<NakedC(NakedArgs...)>, Id<RemoveAnnotations(Type<NakedArgs>)>...); 1113 }; 1114 1115 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename NakedC, 1116 typename... NakedArgs> 1117 struct apply<Comp, TargetRequirements, TargetNonConstRequirements, 1118 Type<std::function<std::unique_ptr<NakedC>(NakedArgs...)>>> { 1119 using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements, 1120 FindInMap(typename Comp::InterfaceBindings, Type<NakedC>), 1121 HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>), 1122 Type<std::unique_ptr<NakedC>>, Type<std::unique_ptr<NakedC>(NakedArgs...)>, 1123 Id<RemoveAnnotations(Type<NakedArgs>)>...); 1124 }; 1125 1126 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename Annotation, 1127 typename NakedC, typename... NakedArgs> 1128 struct apply<Comp, TargetRequirements, TargetNonConstRequirements, 1129 Type<fruit::Annotated<Annotation, std::function<NakedC(NakedArgs...)>>>> { 1130 using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements, 1131 FindInMap(typename Comp::InterfaceBindings, 1132 Type<fruit::Annotated<Annotation, NakedC>>), 1133 HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>), Type<NakedC>, 1134 Type<fruit::Annotated<Annotation, NakedC>(NakedArgs...)>, 1135 Id<RemoveAnnotations(Type<NakedArgs>)>...); 1136 }; 1137 1138 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename Annotation, 1139 typename NakedC, typename... NakedArgs> 1140 struct apply<Comp, TargetRequirements, TargetNonConstRequirements, 1141 Type<fruit::Annotated<Annotation, std::function<std::unique_ptr<NakedC>(NakedArgs...)>>>> { 1142 using type = AutoRegisterFactoryHelper(Comp, TargetRequirements, TargetNonConstRequirements, 1143 FindInMap(typename Comp::InterfaceBindings, 1144 Type<fruit::Annotated<Annotation, NakedC>>), 1145 HasInjectAnnotation(Type<NakedC>), IsAbstract(Type<NakedC>), 1146 Type<std::unique_ptr<NakedC>>, 1147 Type<fruit::Annotated<Annotation, std::unique_ptr<NakedC>>(NakedArgs...)>, 1148 Id<RemoveAnnotations(Type<NakedArgs>)>...); 1149 }; 1150 }; 1151 1152 template <typename AnnotatedT> 1153 struct EnsureProvidedTypeErrorHandler { 1154 template <typename E> 1155 struct apply { 1156 using type = E; 1157 }; 1158 1159 template <typename T> 1160 struct apply<Error<NoBindingFoundErrorTag, T>> { 1161 using type = If(IsSame(Type<T>, AnnotatedT), 1162 ConstructError(ConstBindingDeclaredAsRequiredButNonConstBindingRequiredErrorTag, AnnotatedT), 1163 ConstructError(NoBindingFoundErrorTag, Type<T>)); 1164 }; 1165 1166 template <typename T1, typename T2> 1167 struct apply<Error<NoBindingFoundForAbstractClassErrorTag, T1, T2>> { 1168 using type = If(IsSame(Type<T1>, AnnotatedT), 1169 ConstructError(ConstBindingDeclaredAsRequiredButNonConstBindingRequiredErrorTag, AnnotatedT), 1170 ConstructError(NoBindingFoundForAbstractClassErrorTag, Type<T1>, Type<T2>)); 1171 }; 1172 }; 1173 1174 struct EnsureProvidedType { 1175 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename AnnotatedT, 1176 typename NonConstBindingRequired> 1177 struct apply { 1178 using AnnotatedC = NormalizeType(AnnotatedT); 1179 using AnnotatedCImpl = FindInMap(typename Comp::InterfaceBindings, AnnotatedC); 1180 using AutoRegisterResult = AutoRegister(Comp, TargetRequirements, TargetNonConstRequirements, AnnotatedC); 1181 using ErrorHandler = EnsureProvidedTypeErrorHandler<AnnotatedT>; 1182 using type = If( 1183 IsInSet(AnnotatedC, typename Comp::Ps), 1184 If(And(NonConstBindingRequired, Not(IsInSet(AnnotatedC, typename Comp::NonConstRsPs))), 1185 ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag, AnnotatedC), 1186 ComponentFunctorIdentity(Comp)), 1187 If(And(IsInSet(AnnotatedC, TargetRequirements), 1188 Or(Not(NonConstBindingRequired), IsInSet(AnnotatedC, TargetNonConstRequirements))), 1189 // The type is already in the target requirements with the desired constness, nothing to do. 1190 ComponentFunctorIdentity(Comp), 1191 If(Not(IsNone(AnnotatedCImpl)), 1192 // Has an interface binding. 1193 Call(ComposeFunctors(ComponentFunctor(ProcessInterfaceBinding, AnnotatedC, AnnotatedCImpl, 1194 NonConstBindingRequired), 1195 ComponentFunctor(EnsureProvidedType, TargetRequirements, TargetNonConstRequirements, 1196 AnnotatedCImpl, NonConstBindingRequired)), 1197 Comp), 1198 // If we are about to report a NoBindingFound/NoBindingFoundForAbstractClass error for AnnotatedT and the 1199 // target 1200 // component has a Required<const T>, we can report a more specific error (rather than the usual 1201 // "binding not found"). 1202 If(And(NonConstBindingRequired, IsInSet(AnnotatedC, TargetRequirements)), 1203 Catch(Catch(AutoRegisterResult, NoBindingFoundErrorTag, ErrorHandler), 1204 NoBindingFoundForAbstractClassErrorTag, ErrorHandler), 1205 AutoRegisterResult)))); 1206 }; 1207 }; 1208 1209 struct EnsureProvidedTypes { 1210 template <typename Comp, typename TargetRequirements, typename TargetNonConstRequirements, typename TypesToProvide, 1211 typename NonConstTypesToProvide> 1212 struct apply { 1213 struct Helper { 1214 template <typename CurrentResult, typename T> 1215 struct apply { 1216 using type = Compose2ComponentFunctors(ComponentFunctor(EnsureProvidedType, TargetRequirements, 1217 TargetNonConstRequirements, T, 1218 IsInSet(T, NonConstTypesToProvide)), 1219 CurrentResult); 1220 }; 1221 }; 1222 1223 using type = Call(FoldVector(TypesToProvide, Helper, ComponentFunctorIdentity), Comp); 1224 }; 1225 }; 1226 1227 struct ProcessBinding { 1228 template <typename Binding> 1229 struct apply; 1230 1231 template <typename I, typename C> 1232 struct apply<fruit::impl::Bind<I, C>> { 1233 using type = ComponentFunctor(AddDeferredInterfaceBinding, Type<I>, Type<C>); 1234 }; 1235 1236 template <typename Signature> 1237 struct apply<fruit::impl::RegisterConstructor<Signature>> { 1238 using type = ComponentFunctor(DeferredRegisterConstructor, Type<Signature>); 1239 }; 1240 1241 template <typename AnnotatedC, typename C> 1242 struct apply<fruit::impl::BindInstance<AnnotatedC, C>> { 1243 using type = ComponentFunctor(RegisterInstance, Type<AnnotatedC>, Type<C>, Bool<true>); 1244 }; 1245 1246 template <typename AnnotatedC, typename C> 1247 struct apply<fruit::impl::BindConstInstance<AnnotatedC, C>> { 1248 using type = ComponentFunctor(RegisterInstance, Type<AnnotatedC>, Type<C>, Bool<false>); 1249 }; 1250 1251 template <typename Lambda> 1252 struct apply<fruit::impl::RegisterProvider<Lambda>> { 1253 using type = ComponentFunctor(DeferredRegisterProvider, Type<Lambda>); 1254 }; 1255 1256 template <typename AnnotatedSignature, typename Lambda> 1257 struct apply<fruit::impl::RegisterProvider<AnnotatedSignature, Lambda>> { 1258 using type = ComponentFunctor(DeferredRegisterProviderWithAnnotations, Type<AnnotatedSignature>, Type<Lambda>); 1259 }; 1260 1261 template <typename AnnotatedC> 1262 struct apply<fruit::impl::AddInstanceMultibinding<AnnotatedC>> { 1263 using type = ComponentFunctorIdentity; 1264 }; 1265 1266 template <typename AnnotatedC> 1267 struct apply<fruit::impl::AddInstanceVectorMultibindings<AnnotatedC>> { 1268 using type = ComponentFunctorIdentity; 1269 }; 1270 1271 template <typename I, typename C> 1272 struct apply<fruit::impl::AddMultibinding<I, C>> { 1273 using type = ComponentFunctor(AddInterfaceMultibinding, Type<I>, Type<C>); 1274 }; 1275 1276 template <typename Lambda> 1277 struct apply<fruit::impl::AddMultibindingProvider<Lambda>> { 1278 using type = ComponentFunctor(RegisterMultibindingProvider, Type<Lambda>); 1279 }; 1280 1281 template <typename AnnotatedSignature, typename Lambda> 1282 struct apply<fruit::impl::AddMultibindingProvider<AnnotatedSignature, Lambda>> { 1283 using type = ComponentFunctor(RegisterMultibindingProviderWithAnnotations, Type<AnnotatedSignature>, Type<Lambda>); 1284 }; 1285 1286 template <typename DecoratedSignature, typename Lambda> 1287 struct apply<fruit::impl::RegisterFactory<DecoratedSignature, Lambda>> { 1288 using type = ComponentFunctor(RegisterFactory, Type<DecoratedSignature>, Type<Lambda>); 1289 }; 1290 1291 template <typename... Params, typename... Args> 1292 struct apply<fruit::impl::InstallComponent<fruit::Component<Params...>(Args...)>> { 1293 using type = ComponentFunctor(InstallComponentHelper, Type<Params>...); 1294 }; 1295 1296 template <typename... ComponentFunctions> 1297 struct apply<fruit::impl::InstallComponentFunctions<ComponentFunctions...>> { 1298 using type = ComponentFunctor(InstallComponentFunctions, Type<ComponentFunctions>...); 1299 }; 1300 1301 template <typename GetReplacedComponent, typename GetReplacementComponent> 1302 struct apply<fruit::impl::ReplaceComponent<GetReplacedComponent, GetReplacementComponent>> { 1303 using type = ComponentFunctorIdentity; 1304 }; 1305 }; 1306 1307 } // namespace meta 1308 } // namespace impl 1309 } // namespace fruit 1310 1311 #endif // FRUIT_COMPONENT_FUNCTORS_DEFN_H 1312