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_META_COMPONENT_H 18 #define FRUIT_META_COMPONENT_H 19 20 #include <fruit/fruit_forward_decls.h> 21 #include <fruit/impl/fruit_internal_forward_decls.h> 22 #include <fruit/impl/injection_debug_errors.h> 23 #include <fruit/impl/meta/algos.h> 24 #include <fruit/impl/meta/errors.h> 25 #include <fruit/impl/meta/list.h> 26 #include <fruit/impl/meta/map.h> 27 #include <fruit/impl/meta/metaprogramming.h> 28 #include <fruit/impl/meta/numeric_operations.h> 29 #include <fruit/impl/meta/proof_trees.h> 30 #include <fruit/impl/meta/set.h> 31 #include <fruit/impl/meta/signatures.h> 32 #include <fruit/impl/meta/wrappers.h> 33 34 #include <memory> 35 #include <type_traits> 36 37 namespace fruit { 38 namespace impl { 39 namespace meta { 40 41 //******************************************************************************************************************************** 42 // Part 1: Simple type functors (no ConsComp involved). 43 //******************************************************************************************************************************** 44 45 // Given a type T, returns the class that should be injected to ensure that T is provided at runtime (if any). 46 struct GetClassForType { 47 // General case, if none of the following apply. 48 // When adding a specialization here, make sure that the ComponentStorage 49 // can actually get<> the specified type when the class was registered. 50 template <typename T> 51 struct apply; 52 53 template <typename T> 54 struct apply<Type<T>> { 55 using type = Type<T>; 56 }; 57 58 template <typename T> 59 struct apply<Type<const T>> { 60 using type = Type<T>; 61 }; 62 63 template <typename T> 64 struct apply<Type<T*>> { 65 using type = Type<T>; 66 }; 67 68 template <typename T> 69 struct apply<Type<T&>> { 70 using type = Type<T>; 71 }; 72 73 template <typename T> 74 struct apply<Type<const T*>> { 75 using type = Type<T>; 76 }; 77 78 template <typename T> 79 struct apply<Type<const T&>> { 80 using type = Type<T>; 81 }; 82 83 template <typename T> 84 struct apply<Type<std::shared_ptr<T>>> { 85 using type = Type<T>; 86 }; 87 88 template <typename T> 89 struct apply<Type<Assisted<T>>> { 90 using type = None; 91 }; 92 93 template <typename T> 94 struct apply<Type<Provider<T>>> { 95 using type = Type<T>; 96 }; 97 98 template <typename T> 99 struct apply<Type<Provider<const T>>> { 100 using type = Type<T>; 101 }; 102 103 template <typename Annotation, typename T> 104 struct apply<Type<fruit::Annotated<Annotation, T>>> { 105 using type = Type<T>; 106 }; 107 }; 108 109 struct GetClassForTypeVector { 110 template <typename V> 111 struct apply { 112 using type = TransformVector(V, GetClassForType); 113 }; 114 }; 115 116 // Given a type T, returns the type in the injection graph that corresponds to T. 117 struct NormalizeType { 118 // When adding a specialization here, make sure that the ComponentStorage 119 // can actually get<> the specified type when the class was registered. 120 template <typename T> 121 struct apply; 122 123 template <typename T> 124 struct apply<Type<T>> { 125 using type = Type<T>; 126 }; 127 128 template <typename T> 129 struct apply<Type<const T>> { 130 using type = Type<T>; 131 }; 132 133 template <typename T> 134 struct apply<Type<T*>> { 135 using type = Type<T>; 136 }; 137 138 template <typename T> 139 struct apply<Type<T&>> { 140 using type = Type<T>; 141 }; 142 143 template <typename T> 144 struct apply<Type<const T*>> { 145 using type = Type<T>; 146 }; 147 148 template <typename T> 149 struct apply<Type<const T&>> { 150 using type = Type<T>; 151 }; 152 153 template <typename T> 154 struct apply<Type<std::shared_ptr<T>>> { 155 using type = Type<T>; 156 }; 157 158 template <typename T> 159 struct apply<Type<Assisted<T>>> { 160 using type = None; 161 }; 162 163 template <typename T> 164 struct apply<Type<Provider<T>>> { 165 using type = Type<T>; 166 }; 167 168 template <typename T> 169 struct apply<Type<Provider<const T>>> { 170 using type = Type<T>; 171 }; 172 173 template <typename Annotation, typename T> 174 struct apply<Type<fruit::Annotated<Annotation, T>>> { 175 using type = Type<fruit::Annotated<Annotation, UnwrapType<Eval<NormalizeType(Type<T>)>>>>; 176 }; 177 }; 178 179 struct NormalizeUntilStable { 180 template <typename T> 181 struct apply { 182 using type = If(IsSame(NormalizeType(T), T), T, NormalizeUntilStable(NormalizeType(T))); 183 }; 184 }; 185 186 struct NormalizeTypeVector { 187 template <typename V> 188 struct apply { 189 using type = TransformVector(V, NormalizeType); 190 }; 191 }; 192 193 struct TypeInjectionRequiresNonConstBinding { 194 template <typename T> 195 struct apply; 196 197 template <typename T> 198 struct apply<Type<T>> { 199 using type = Bool<false>; 200 }; 201 202 template <typename T> 203 struct apply<Type<const T>> { 204 using type = Bool<false>; 205 }; 206 207 template <typename T> 208 struct apply<Type<T*>> { 209 using type = Bool<true>; 210 }; 211 212 template <typename T> 213 struct apply<Type<T&>> { 214 using type = Bool<true>; 215 }; 216 217 template <typename T> 218 struct apply<Type<const T*>> { 219 using type = Bool<false>; 220 }; 221 222 template <typename T> 223 struct apply<Type<const T&>> { 224 using type = Bool<false>; 225 }; 226 227 template <typename T> 228 struct apply<Type<std::shared_ptr<T>>> { 229 using type = Bool<true>; 230 }; 231 232 template <typename T> 233 struct apply<Type<Assisted<T>>> { 234 using type = Bool<false>; 235 }; 236 237 template <typename T> 238 struct apply<Type<Provider<T>>> { 239 using type = Bool<true>; 240 }; 241 242 template <typename T> 243 struct apply<Type<Provider<const T>>> { 244 using type = Bool<false>; 245 }; 246 247 template <typename Annotation, typename T> 248 struct apply<Type<fruit::Annotated<Annotation, T>>> { 249 using type = TypeInjectionRequiresNonConstBinding(Type<T>); 250 }; 251 }; 252 253 // Returns U wrapped in the same annotations in AnnotatedT (if any). 254 struct CopyAnnotation { 255 template <typename AnnotatedT, typename U> 256 struct apply; 257 258 template <typename T, typename U> 259 struct apply { 260 using type = U; 261 }; 262 263 template <typename Annotation, typename T, typename U> 264 struct apply<Type<fruit::Annotated<Annotation, T>>, Type<U>> { 265 using type = Type<fruit::Annotated<Annotation, U>>; 266 }; 267 }; 268 269 struct IsValidSignature { 270 template <typename Signature> 271 struct apply { 272 using type = Bool<false>; 273 }; 274 275 template <typename T, typename... Args> 276 struct apply<Type<T(Args...)>> { 277 using type = Bool<true>; 278 }; 279 }; 280 281 // Removes the Annotation (if any) wrapping a type T. 282 struct RemoveAnnotations { 283 template <typename T> 284 struct apply; 285 286 template <typename T> 287 struct apply<Type<T>> { 288 using type = Type<T>; 289 }; 290 291 template <typename Annotation, typename T> 292 struct apply<Type<fruit::Annotated<Annotation, T>>> { 293 using type = Type<T>; 294 }; 295 }; 296 297 // Removes the Annotation(s) (if any) wrapping the types in AnnotatedSignature. 298 struct RemoveAnnotationsFromSignature { 299 template <typename AnnotatedSignature> 300 struct apply { 301 using type = ConstructError(NotASignatureErrorTag, AnnotatedSignature); 302 }; 303 304 template <typename AnnotatedT, typename... AnnotatedArgs> 305 struct apply<Type<AnnotatedT(AnnotatedArgs...)>> { 306 using type = ConsSignature(RemoveAnnotations(Type<AnnotatedT>), Id<RemoveAnnotations(Type<AnnotatedArgs>)>...); 307 }; 308 }; 309 310 // Removes the Annotation(s) (if any) wrapping the types in the Vector V. 311 struct RemoveAnnotationsFromVector { 312 template <typename V> 313 struct apply { 314 using type = TransformVector(V, RemoveAnnotations); 315 }; 316 }; 317 318 // Maps T->T* in a possibly-annotated type. 319 struct AddPointerInAnnotatedType { 320 template <typename T> 321 struct apply; 322 323 template <typename T> 324 struct apply<Type<T>> { 325 using type = Type<T*>; 326 }; 327 328 template <typename Annotation, typename T> 329 struct apply<Type<fruit::Annotated<Annotation, T>>> { 330 using type = Type<fruit::Annotated<Annotation, T*>>; 331 }; 332 }; 333 334 // TODO: This also does UnlabelAssisted<>. Consider renaming and/or removing that logic (and 335 // letting callers do the unlabeling when desired). 336 struct RemoveNonAssisted { 337 template <typename V> 338 struct apply { 339 struct Helper { 340 // Non-assisted case 341 template <typename CurrentResult, typename T> 342 struct apply { 343 using type = CurrentResult; 344 }; 345 346 template <typename CurrentResult, typename T> 347 struct apply<CurrentResult, Type<Assisted<T>>> { 348 using type = PushBack(CurrentResult, Type<T>); 349 }; 350 }; 351 352 using type = FoldVector(V, Helper, Vector<>); 353 }; 354 }; 355 356 struct RemoveAssisted { 357 template <typename V> 358 struct apply { 359 struct Helper { 360 // Non-assisted case 361 template <typename CurrentResult, typename T> 362 struct apply { 363 using type = PushBack(CurrentResult, T); 364 }; 365 366 // Assisted case 367 template <typename CurrentResult, typename T> 368 struct apply<CurrentResult, Type<Assisted<T>>> { 369 using type = CurrentResult; 370 }; 371 }; 372 373 using type = FoldVector(V, Helper, Vector<>); 374 }; 375 }; 376 377 struct UnlabelAssistedSingleType { 378 template <typename T> 379 struct apply; 380 381 template <typename T> 382 struct apply<Type<T>> { 383 using type = Type<T>; 384 }; 385 386 template <typename T> 387 struct apply<Type<Assisted<T>>> { 388 using type = Type<T>; 389 }; 390 }; 391 392 struct UnlabelAssisted { 393 template <typename V> 394 struct apply { 395 using type = TransformVector(V, UnlabelAssistedSingleType); 396 }; 397 }; 398 399 struct RequiredLambdaArgsForAssistedFactory { 400 template <typename AnnotatedSignature> 401 struct apply { 402 using type = RemoveAnnotationsFromVector(UnlabelAssisted(SignatureArgs(AnnotatedSignature))); 403 }; 404 }; 405 406 struct RequiredLambdaSignatureForAssistedFactory { 407 template <typename AnnotatedSignature> 408 struct apply { 409 using type = ConsSignatureWithVector(RemoveAnnotations(SignatureType(AnnotatedSignature)), 410 RequiredLambdaArgsForAssistedFactory(AnnotatedSignature)); 411 }; 412 }; 413 414 struct InjectedFunctionArgsForAssistedFactory { 415 template <typename AnnotatedSignature> 416 struct apply { 417 using type = RemoveNonAssisted(SignatureArgs(AnnotatedSignature)); 418 }; 419 }; 420 421 struct InjectedSignatureForAssistedFactory { 422 template <typename AnnotatedSignature> 423 struct apply { 424 using type = ConsSignatureWithVector(RemoveAnnotations(SignatureType(AnnotatedSignature)), 425 InjectedFunctionArgsForAssistedFactory(AnnotatedSignature)); 426 }; 427 }; 428 429 struct IsAssisted { 430 template <typename T> 431 struct apply { 432 using type = Bool<false>; 433 }; 434 435 template <typename T> 436 struct apply<Type<Assisted<T>>> { 437 using type = Bool<true>; 438 }; 439 }; 440 441 struct NumAssisted { 442 template <typename V> 443 struct apply; 444 445 template <typename... Types> 446 struct apply<Vector<Types...>> { 447 using type = SumAll(typename IsAssisted::apply<Types>::type...); 448 }; 449 }; 450 451 // Counts the number of Assisted<> types in V before the given index. 452 struct NumAssistedBefore { 453 template <typename Index, typename V> 454 struct apply; 455 456 template <typename V> 457 struct apply<Int<0>, V> { 458 using type = Int<0>; 459 }; 460 461 template <int n, typename V> 462 struct apply<Int<n>, V> { 463 using N = Int<n>; 464 using type = Minus(NumAssisted(V), NumAssisted(VectorRemoveFirstN(V, N))); 465 }; 466 }; 467 468 // Checks whether C is auto-injectable thanks to an Inject typedef. 469 struct HasInjectAnnotation { 470 template <typename C> 471 struct apply; 472 473 template <typename C> 474 struct apply<Type<C>> { 475 template <typename C1> 476 static Bool<true> test(typename C1::Inject*); 477 478 template <typename> 479 static Bool<false> test(...); 480 481 using type = decltype(test<C>(nullptr)); 482 }; 483 }; 484 485 struct DoGetInjectAnnotation { 486 template <typename C> 487 struct apply; 488 489 template <typename C> 490 struct apply<Type<C>> { 491 using type = Type<typename C::Inject>; 492 }; 493 }; 494 495 struct GetInjectAnnotation { 496 template <typename AnnotatedC> 497 struct apply { 498 using C = RemoveAnnotations(AnnotatedC); 499 using DecoratedS = DoGetInjectAnnotation(C); 500 using SResult = SignatureType(DecoratedS); 501 using AnnotatedSArgs = SignatureArgs(DecoratedS); 502 using SArgs = RemoveAnnotationsFromVector(UnlabelAssisted(AnnotatedSArgs)); 503 // We replace the non-annotated return type with the potentially-annotated AnnotatedC. 504 using AnnotatedDecoratedS = ConsSignatureWithVector(AnnotatedC, AnnotatedSArgs); 505 using type = If(IsAbstract(C), ConstructError(CannotConstructAbstractClassErrorTag, C), 506 If(Not(IsValidSignature(DecoratedS)), 507 ConstructError(InjectTypedefNotASignatureErrorTag, C, DecoratedS), 508 If(Not(IsSame(SResult, RemoveAnnotations(SResult))), 509 ConstructError(InjectTypedefWithAnnotationErrorTag, C), 510 If(Not(IsSame(C, SResult)), ConstructError(InjectTypedefForWrongClassErrorTag, C, SResult), 511 If(Not(IsConstructibleWithVector(C, SArgs)), 512 ConstructError(NoConstructorMatchingInjectSignatureErrorTag, C, 513 ConsSignatureWithVector(SResult, SArgs)), 514 AnnotatedDecoratedS))))); 515 }; 516 }; 517 518 //******************************************************************************************************************************** 519 // Part 2: Type functors involving at least one ConsComp. 520 //******************************************************************************************************************************** 521 522 template <typename RsSupersetParam, typename PsParam, typename NonConstRsPsParam, 523 #if !FRUIT_NO_LOOP_CHECK 524 typename DepsParam, 525 #endif 526 typename InterfaceBindingsParam, typename DeferredBindingFunctorsParam> 527 struct Comp { 528 // The actual set of requirements is SetDifference(RsSuperset, Ps) 529 // We don't store Rs explicitly because we'd need to remove elements very often (and that's slow). 530 using RsSuperset = RsSupersetParam; 531 532 using Ps = PsParam; 533 // This is a set of normalized types. 534 // - If a type is in SetDifference(RsSuperset, Ps) and not here: it's required as const only 535 // - If a type is in SetDifference(RsSuperset, Ps) and also here: it's required as non-const 536 // - If a type is in Ps and not here: it's provided as const only 537 // - If a type is in Ps and also here: it's provided as non-const 538 using NonConstRsPs = NonConstRsPsParam; 539 #if !FRUIT_NO_LOOP_CHECK 540 using Deps = DepsParam; 541 #endif 542 using InterfaceBindings = InterfaceBindingsParam; 543 using DeferredBindingFunctors = DeferredBindingFunctorsParam; 544 545 // Invariants: 546 // * all types appearing as arguments of Deps are in Rs 547 // * all types in Ps are at the head of one (and only one) Dep. 548 // (note that the types in Rs can appear in deps any number of times, 0 is also ok) 549 // * Deps is of the form Vector<Dep...> with each Dep of the form T(Args...) and where Vector<Args...> is a set (no 550 // repetitions). 551 // * Bindings is a proof tree forest, with injected classes as formulas. 552 // * Each element X of the list DeferredBindingFunctors has: 553 // - a default-constructible X::apply<Comp> type 554 // - a void X::apply<Comp>::operator(ComponentStorage&) 555 // - an X::apply<Comp>::Result type 556 // * Each element of NonConstRsPs is in RsSuperset or in Ps (or both) 557 }; 558 559 // Using ConsComp instead of Comp<...> in a meta-expression allows the types to be evaluated. 560 // See ConsVector for more details. 561 struct ConsComp { 562 template <typename RsSupersetParam, typename PsParam, typename NonConstRsPsParam, 563 #if !FRUIT_NO_LOOP_CHECK 564 typename DepsParam, 565 #endif 566 typename InterfaceBindingsParam, typename DeferredBindingFunctorsParam> 567 struct apply { 568 using type = Comp<RsSupersetParam, PsParam, NonConstRsPsParam, 569 #if !FRUIT_NO_LOOP_CHECK 570 DepsParam, 571 #endif 572 InterfaceBindingsParam, DeferredBindingFunctorsParam>; 573 }; 574 }; 575 576 struct GetComponentDeps { 577 template <typename Comp> 578 struct apply { 579 using type = typename Comp::Deps; 580 }; 581 }; 582 583 struct GetComponentPs { 584 template <typename Comp> 585 struct apply { 586 using type = typename Comp::Ps; 587 }; 588 }; 589 590 struct GetComponentRsSuperset { 591 template <typename Comp> 592 struct apply { 593 using type = typename Comp::RsSuperset; 594 }; 595 }; 596 597 struct GetComponentNonConstRsPs { 598 template <typename Comp> 599 struct apply { 600 using type = typename Comp::NonConstRsPs; 601 }; 602 }; 603 604 struct IsInjectableBareType { 605 template <typename T> 606 struct apply; 607 608 template <typename T> 609 struct apply<Type<T>> { 610 using type = Bool<std::is_arithmetic<T>::value || std::is_class<T>::value || std::is_enum<T>::value>; 611 }; 612 613 template <typename Annotation, typename T> 614 struct apply<Type<fruit::Annotated<Annotation, T>>> { 615 using type = Bool<false>; 616 }; 617 618 template <typename T> 619 struct apply<Type<std::shared_ptr<T>>> { 620 using type = Bool<false>; 621 }; 622 }; 623 624 // Checks if T is a (non-annotated) injectable type. 625 struct IsInjectableType { 626 template <typename T> 627 struct apply { 628 using type = IsInjectableBareType(NormalizeType(T)); 629 }; 630 }; 631 632 // Checks that T is a (non-annotated) injectable type. If it isn't this returns an error, otherwise it returns None. 633 struct CheckInjectableType { 634 template <typename T> 635 struct apply { 636 using type = If(Not(IsInjectableType(T)), ConstructError(NonInjectableTypeErrorTag, T), None); 637 }; 638 }; 639 640 // Checks that Types... are (non-annotated) injectable types. If they have an annotation or they are not injectable it 641 // an appropriate error is returned. 642 // Otherwise this returns None. 643 struct CheckInjectableTypeVector { 644 struct Helper { 645 template <typename CurrentResult, typename T> 646 struct apply { 647 using type = PropagateError(CheckInjectableType(T), CurrentResult); 648 }; 649 }; 650 651 template <typename V> 652 struct apply { 653 using type = FoldVector(V, Helper, None); 654 }; 655 }; 656 657 // Checks that Types... are normalized and injectable types. If not it returns an appropriate error. 658 // If they are all normalized types this returns Result. 659 struct CheckNormalizedTypes { 660 template <typename V> 661 struct apply; 662 663 template <typename... Types> 664 struct apply<Vector<Type<Types>...>> { 665 struct Helper { 666 template <typename CurrentResult, typename T> 667 struct apply { 668 using NormalizedType = NormalizeType(T); 669 using type = PropagateError(CheckInjectableType(RemoveAnnotations(NormalizeUntilStable(T))), 670 If(Not(IsSame(NormalizeType(T), T)), 671 ConstructError(NonClassTypeErrorTag, RemoveAnnotations(T), 672 RemoveAnnotations(NormalizeUntilStable(T))), 673 CurrentResult)); 674 }; 675 }; 676 677 using type = Fold(Helper, None, Type<Types>...); 678 }; 679 }; 680 681 // Checks that Types... are not annotated types. If they have an annotation it returns an appropriate error. 682 // If none of them is annotated, this returns None. 683 struct CheckNotAnnotatedTypes { 684 template <typename V> 685 struct apply; 686 687 template <typename... Types> 688 struct apply<Vector<Type<Types>...>> { 689 struct Helper { 690 template <typename CurrentResult, typename T> 691 struct apply { 692 using TypeWithoutAnnotations = RemoveAnnotations(T); 693 using type = If(Not(IsSame(TypeWithoutAnnotations, T)), 694 ConstructError(AnnotatedTypeErrorTag, T, TypeWithoutAnnotations), CurrentResult); 695 }; 696 }; 697 698 using type = Fold(Helper, None, Type<Types>...); 699 }; 700 }; 701 702 // Check that there are no fruit::Required<> types in Component/NormalizedComponent's arguments. 703 // If there aren't any, this returns None. 704 struct CheckNoRequiredTypesInComponentArguments { 705 template <typename V> 706 struct apply; 707 708 template <typename... Types> 709 struct apply<Vector<Types...>> { 710 using type = None; 711 }; 712 713 template <typename T, typename... OtherTypes> 714 struct apply<Vector<Type<T>, OtherTypes...>> { 715 using type = CheckNoRequiredTypesInComponentArguments(Vector<OtherTypes...>); 716 }; 717 718 template <typename... RequiredArgs, typename... OtherTypes> 719 struct apply<Vector<Type<fruit::Required<RequiredArgs...>>, OtherTypes...>> { 720 using type = ConstructError(RequiredTypesInComponentArgumentsErrorTag, Type<fruit::Required<RequiredArgs...>>); 721 }; 722 }; 723 724 // Check that there are no fruit::Required<> types in Injector's arguments. 725 // If there aren't any, this returns None. 726 struct CheckNoRequiredTypesInInjectorArguments { 727 template <typename... Types> 728 struct apply { 729 using type = None; 730 }; 731 732 template <typename T, typename... Types> 733 struct apply<T, Types...> { 734 using type = CheckNoRequiredTypesInInjectorArguments(Types...); 735 }; 736 737 template <typename... RequiredArgs, typename... Types> 738 struct apply<Type<fruit::Required<RequiredArgs...>>, Types...> { 739 using type = ConstructError(InjectorWithRequirementsErrorTag, Type<RequiredArgs>...); 740 }; 741 }; 742 743 // Checks that there are no repetitions in Types. If there are, it returns an appropriate error. 744 // If there are no repetitions it returns None. 745 struct CheckNoRepeatedTypes { 746 template <typename V> 747 struct apply; 748 749 template <typename... Types> 750 struct apply<Vector<Types...>> { 751 using type = If(HasDuplicates(Vector<Types...>), ConstructError(RepeatedTypesErrorTag, Types...), None); 752 }; 753 }; 754 755 struct RemoveConstFromType { 756 template <typename T> 757 struct apply; 758 759 template <typename T> 760 struct apply<Type<T>> { 761 using type = Type<T>; 762 }; 763 764 template <typename T> 765 struct apply<Type<const T>> { 766 using type = Type<T>; 767 }; 768 769 template <typename Annotation, typename T> 770 struct apply<Type<fruit::Annotated<Annotation, T>>> { 771 using type = Type<fruit::Annotated<Annotation, T>>; 772 }; 773 774 template <typename Annotation, typename T> 775 struct apply<Type<fruit::Annotated<Annotation, const T>>> { 776 using type = Type<fruit::Annotated<Annotation, T>>; 777 }; 778 }; 779 780 struct RemoveConstFromTypes { 781 template <typename V> 782 struct apply; 783 784 template <typename... Types> 785 struct apply<Vector<Types...>> { 786 using type = ConsVector(Id<RemoveConstFromType(Types)>...); 787 }; 788 }; 789 790 struct RemoveConstTypes { 791 struct Helper { 792 template <typename Acc, typename T> 793 struct apply; 794 795 template <typename... AccContent, typename T> 796 struct apply<Vector<AccContent...>, Type<const T>> { 797 using type = Vector<AccContent...>; 798 }; 799 800 template <typename... AccContent, typename T> 801 struct apply<Vector<AccContent...>, Type<T>> { 802 using type = Vector<AccContent..., Type<T>>; 803 }; 804 805 template <typename... AccContent, typename Annotation, typename T> 806 struct apply<Vector<AccContent...>, Type<fruit::Annotated<Annotation, const T>>> { 807 using type = Vector<AccContent...>; 808 }; 809 810 template <typename... AccContent, typename Annotation, typename T> 811 struct apply<Vector<AccContent...>, Type<fruit::Annotated<Annotation, T>>> { 812 using type = Vector<AccContent..., Type<fruit::Annotated<Annotation, T>>>; 813 }; 814 }; 815 816 template <typename V> 817 struct apply { 818 using type = FoldVector(V, Helper, Vector<>); 819 }; 820 }; 821 822 // From a vector of injected types, this filters out the types that only require const bindings and then normalizes 823 // the types in the result. 824 struct NormalizedNonConstTypesIn { 825 struct Helper { 826 template <typename Acc, typename T> 827 struct apply { 828 using type = If(TypeInjectionRequiresNonConstBinding(T), PushBack(Acc, NormalizeType(T)), Acc); 829 }; 830 }; 831 832 template <typename V> 833 struct apply { 834 using type = FoldVector(V, Helper, Vector<>); 835 }; 836 }; 837 838 struct ConstructComponentImpl { 839 // Non-specialized case: no requirements. 840 template <typename... Ps> 841 struct apply { 842 using type = PropagateError( 843 CheckNoRepeatedTypes(RemoveConstFromTypes(Vector<Ps...>)), 844 PropagateError(CheckNormalizedTypes(RemoveConstFromTypes(Vector<Ps...>)), 845 PropagateError(CheckNoRequiredTypesInComponentArguments(Vector<Ps...>), 846 ConsComp(EmptySet, VectorToSetUnchecked(RemoveConstFromTypes(Vector<Ps...>)), 847 RemoveConstTypes(Vector<Ps...>), 848 #if !FRUIT_NO_LOOP_CHECK 849 Vector<Pair<Ps, Vector<>>...>, 850 #endif 851 Vector<>, EmptyList)))); 852 }; 853 854 // With requirements. 855 template <typename... Rs, typename... Ps> 856 struct apply<Type<Required<Rs...>>, Ps...> { 857 using type1 = PropagateError( 858 CheckNoRepeatedTypes(RemoveConstFromTypes(Vector<Type<Rs>..., Ps...>)), 859 PropagateError(CheckNormalizedTypes(RemoveConstFromTypes(Vector<Type<Rs>..., Ps...>)), 860 PropagateError(CheckNoRequiredTypesInComponentArguments(Vector<Ps...>), 861 ConsComp(VectorToSetUnchecked(RemoveConstFromTypes(Vector<Type<Rs>...>)), 862 VectorToSetUnchecked(RemoveConstFromTypes(Vector<Ps...>)), 863 RemoveConstTypes(Vector<Type<Rs>..., Ps...>), 864 #if !FRUIT_NO_LOOP_CHECK 865 Vector<Pair<Ps, Vector<Type<Rs>...>>...>, 866 #endif 867 Vector<>, EmptyList)))); 868 869 #if !FRUIT_NO_LOOP_CHECK && FRUIT_EXTRA_DEBUG 870 using Loop = ProofForestFindLoop(GetComponentDeps(type1)); 871 using type = If(IsNone(Loop), type1, ConstructErrorWithArgVector(SelfLoopErrorTag, Loop)); 872 #else // FRUIT_NO_LOOP_CHECK || !FRUIT_EXTRA_DEBUG 873 using type = type1; 874 #endif // FRUIT_NO_LOOP_CHECK || !FRUIT_EXTRA_DEBUG 875 }; 876 }; 877 878 struct CheckTypesNotProvidedAsConst { 879 template <typename Comp, typename V> 880 struct apply { 881 struct Helper { 882 template <typename Acc, typename T> 883 struct apply { 884 using type = If(And(IsInSet(T, typename Comp::Ps), Not(IsInSet(T, typename Comp::NonConstRsPs))), 885 ConstructError(NonConstBindingRequiredButConstBindingProvidedErrorTag, T), Acc); 886 }; 887 }; 888 889 using type = FoldVector(V, Helper, None); 890 }; 891 }; 892 893 // Adds the types in NewRequirementsVector to the requirements (unless they are already provided/required). 894 // The caller must convert the types to the corresponding class type and expand any Provider<>s. 895 struct AddRequirements { 896 template <typename Comp, typename NewRequirementsVector, typename NewNonConstRequirementsVector> 897 struct apply { 898 using Comp1 = ConsComp(FoldVector(NewRequirementsVector, AddToSet, typename Comp::RsSuperset), typename Comp::Ps, 899 FoldVector(NewNonConstRequirementsVector, AddToSet, typename Comp::NonConstRsPs), 900 #if !FRUIT_NO_LOOP_CHECK 901 typename Comp::Deps, 902 #endif 903 typename Comp::InterfaceBindings, typename Comp::DeferredBindingFunctors); 904 using type = PropagateError(CheckTypesNotProvidedAsConst(Comp, NewNonConstRequirementsVector), Comp1); 905 }; 906 }; 907 908 // Similar to AddProvidedType, but doesn't report an error if a Bind<C, CImpl> was present. 909 struct AddProvidedTypeIgnoringInterfaceBindings { 910 template <typename Comp, typename C, typename IsNonConst, typename CRequirements, typename CNonConstRequirements> 911 struct apply { 912 using Comp1 = ConsComp( 913 FoldVector(CRequirements, AddToSet, typename Comp::RsSuperset), AddToSetUnchecked(typename Comp::Ps, C), 914 If(IsNonConst, AddToSetUnchecked(FoldVector(CNonConstRequirements, AddToSet, typename Comp::NonConstRsPs), C), 915 FoldVector(CNonConstRequirements, AddToSet, typename Comp::NonConstRsPs)), 916 #if !FRUIT_NO_LOOP_CHECK 917 PushFront(typename Comp::Deps, Pair<C, CRequirements>), 918 #endif 919 typename Comp::InterfaceBindings, typename Comp::DeferredBindingFunctors); 920 using type = If(IsInSet(C, typename Comp::Ps), ConstructError(TypeAlreadyBoundErrorTag, C), 921 PropagateError(CheckTypesNotProvidedAsConst(Comp, CNonConstRequirements), Comp1)); 922 }; 923 }; 924 925 // Adds C to the provides and removes it from the requirements (if it was there at all). 926 // Also checks that it wasn't already provided. 927 // Moreover, adds the requirements of C to the requirements, unless they were already provided/required. 928 // The caller must convert the types to the corresponding class type and expand any Provider<>s. 929 struct AddProvidedType { 930 template <typename Comp, typename C, typename IsNonConst, typename CRequirements, typename CNonConstRequirements> 931 struct apply { 932 using type = If(Not(IsNone(FindInMap(typename Comp::InterfaceBindings, C))), 933 ConstructError(TypeAlreadyBoundErrorTag, C), 934 AddProvidedTypeIgnoringInterfaceBindings(Comp, C, IsNonConst, CRequirements, 935 CNonConstRequirements)); 936 }; 937 }; 938 939 struct AddDeferredBinding { 940 template <typename Comp, typename DeferredBinding> 941 struct apply { 942 using new_DeferredBindingFunctors = Cons<DeferredBinding, typename Comp::DeferredBindingFunctors>; 943 using type = ConsComp(typename Comp::RsSuperset, typename Comp::Ps, typename Comp::NonConstRsPs, 944 #if !FRUIT_NO_LOOP_CHECK 945 typename Comp::Deps, 946 #endif 947 typename Comp::InterfaceBindings, new_DeferredBindingFunctors); 948 }; 949 }; 950 951 struct CheckNoLoopInDeps { 952 template <typename Comp> 953 struct apply { 954 using Loop = ProofForestFindLoop(typename Comp::Deps); 955 using type = If(IsNone(Loop), Bool<true>, ConstructErrorWithArgVector(SelfLoopErrorTag, Loop)); 956 }; 957 }; 958 959 #if FRUIT_EXTRA_DEBUG || FRUIT_IN_META_TEST 960 struct CheckComponentEntails { 961 template <typename Comp, typename EntailedComp> 962 struct apply { 963 using CompRs = SetDifference(typename Comp::RsSuperset, typename Comp::Ps); 964 using EntailedCompRs = SetDifference(typename EntailedComp::RsSuperset, typename EntailedComp::Ps); 965 using CommonRs = SetIntersection(CompRs, EntailedCompRs); 966 using CommonPs = SetIntersection(typename Comp::Ps, typename EntailedComp::Ps); 967 using type = 968 If(Not(IsContained(typename EntailedComp::Ps, typename Comp::Ps)), 969 ConstructErrorWithArgVector(ComponentDoesNotEntailDueToProvidesErrorTag, 970 SetToVector(SetDifference(typename EntailedComp::Ps, typename Comp::Ps))), 971 If(Not(IsVectorContained(typename EntailedComp::InterfaceBindings, typename Comp::InterfaceBindings)), 972 ConstructErrorWithArgVector(ComponentDoesNotEntailDueToInterfaceBindingsErrorTag, 973 SetToVector(SetDifference(typename EntailedComp::InterfaceBindings, 974 typename Comp::InterfaceBindings))), 975 If(Not(IsContained(CompRs, EntailedCompRs)), 976 ConstructErrorWithArgVector(ComponentDoesNotEntailDueToRequirementsErrorTag, 977 SetToVector(SetDifference(CompRs, EntailedCompRs))), 978 If(Not(IsContained(SetIntersection(CommonRs, typename Comp::NonConstRsPs), 979 typename EntailedComp::NonConstRsPs)), 980 ConstructErrorWithArgVector(ComponentDoesNotEntailDueToDifferentConstnessOfRequirementsErrorTag, 981 SetToVector(SetDifference(SetIntersection(CommonRs, 982 typename Comp::NonConstRsPs), 983 typename EntailedComp::NonConstRsPs))), 984 If(Not(IsContained(SetIntersection(CommonPs, typename EntailedComp::NonConstRsPs), 985 typename Comp::NonConstRsPs)), 986 ConstructErrorWithArgVector( 987 ComponentDoesNotEntailDueToDifferentConstnessOfProvidesErrorTag, 988 SetToVector(SetDifference(SetIntersection(CommonPs, typename EntailedComp::NonConstRsPs), 989 typename Comp::NonConstRsPs))), 990 Bool<true>))))); 991 static_assert(true || sizeof(typename CheckIfError<Eval<type>>::type), ""); 992 }; 993 }; 994 #endif // FRUIT_EXTRA_DEBUG || FRUIT_IN_META_TEST 995 996 // This calls ConstructError(NoBindingFoundErrorTag, ...) or 997 // ConstructError(NoBindingFoundForAbstractClassErrorTag, ...) as appropriate. 998 // Call this when we're unable to auto-inject a type AnnotatedC and we're giving up. 999 struct ConstructNoBindingFoundError { 1000 template <typename AnnotatedC> 1001 struct apply { 1002 using type = If(IsAbstract(RemoveAnnotations(AnnotatedC)), 1003 ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedC, RemoveAnnotations(AnnotatedC)), 1004 ConstructError(NoBindingFoundErrorTag, AnnotatedC)); 1005 }; 1006 }; 1007 1008 } // namespace meta 1009 } // namespace impl 1010 } // namespace fruit 1011 1012 #endif // FRUIT_META_COMPONENT_H 1013