• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_INJECTION_ERRORS_H
18 #define FRUIT_INJECTION_ERRORS_H
19 
20 #include <fruit/impl/fruit_assert.h>
21 #include <fruit/impl/meta/set.h>
22 
23 namespace fruit {
24 namespace impl {
25 
26 template <typename... Ts>
27 struct AlwaysFalse {
28   static constexpr bool value = false;
29 };
30 
31 template <typename T>
32 struct NoBindingFoundError {
33   static_assert(AlwaysFalse<T>::value, "No explicit binding nor C::Inject definition was found for T.");
34 };
35 
36 template <typename T, typename C>
37 struct NoBindingFoundForAbstractClassError {
38   static_assert(AlwaysFalse<T>::value,
39                 "No explicit binding was found for T, and note that C is an abstract class (so Fruit can't auto-inject "
40                 "this type, "
41                 "even if it has an Inject typedef or an INJECT annotation that will be ignored).");
42 };
43 
44 template <typename... Ts>
45 struct RepeatedTypesError {
46   static_assert(AlwaysFalse<Ts...>::value,
47                 "A type was specified more than once. Requirements and provided types should be unique.");
48 };
49 
50 template <typename... TypesInLoop>
51 struct SelfLoopError {
52   static_assert(AlwaysFalse<TypesInLoop...>::value,
53                 "Found a loop in the dependencies! The types in TypesInLoop all depend on the next, and the "
54                 "last one depends on the first.");
55 };
56 
57 template <typename T, typename C>
58 struct NonClassTypeError {
59   static_assert(AlwaysFalse<T>::value, "A non-class type T was specified. Use C instead.");
60 };
61 
62 template <typename AnnotatedT, typename T>
63 struct AnnotatedTypeError {
64   static_assert(AlwaysFalse<T>::value, "An annotated type was specified where a non-annotated type was expected.");
65 };
66 
67 template <typename C>
68 struct TypeAlreadyBoundError {
69   static_assert(AlwaysFalse<C>::value, "Trying to bind C but it is already bound.");
70 };
71 
72 template <typename RequiredSignature, typename SignatureInInjectTypedef>
73 struct RequiredFactoryWithDifferentSignatureError {
74   static_assert(AlwaysFalse<RequiredSignature>::value,
75                 "The required C factory doesn't have the same signature as the Inject annotation in C.");
76 };
77 
78 template <typename Signature, typename SignatureInLambda>
79 struct AnnotatedSignatureDifferentFromLambdaSignatureError {
80   static_assert(AlwaysFalse<Signature>::value,
81                 "The annotated signature specified is not the same as the lambda's signature (after removing "
82                 "annotations).");
83 };
84 
85 template <typename... DuplicatedTypes>
86 struct DuplicateTypesInComponentError {
87   static_assert(AlwaysFalse<DuplicatedTypes...>::value,
88                 "The installed component provides some types that are already provided by the current "
89                 "component.");
90 };
91 
92 template <typename... Requirements>
93 struct InjectorWithRequirementsError {
94   static_assert(AlwaysFalse<Requirements...>::value,
95                 "Injectors can't have requirements. If you want Fruit to try auto-resolving the requirements "
96                 "in the injector's scope, cast the component to a component with no requirements before "
97                 "constructing the injector with it.");
98 };
99 
100 template <typename C, typename CandidateSignature>
101 struct InjectTypedefNotASignatureError {
102   static_assert(AlwaysFalse<C>::value, "C::Inject should be a typedef to a signature, e.g. C(int)");
103 };
104 
105 template <typename C, typename SignatureReturnType>
106 struct InjectTypedefForWrongClassError {
107   static_assert(AlwaysFalse<C>::value,
108                 "C::Inject is a signature, but does not return a C. Maybe the class C has no Inject typedef "
109                 "and inherited the base class' one? If that's not the case, make sure it returns just C, not "
110                 "C* or other types.");
111 };
112 
113 template <typename C>
114 struct InjectTypedefWithAnnotationError {
115   static_assert(AlwaysFalse<C>::value,
116                 "C::Inject is a signature that returns an annotated type. The annotation must be removed, "
117                 "Fruit will deduce the correct annotation based on how the required binding.");
118 };
119 
120 template <typename CandidateSignature>
121 struct NotASignatureError {
122   static_assert(AlwaysFalse<CandidateSignature>::value,
123                 "CandidateSignature was specified as parameter, but it's not a signature. Signatures are of "
124                 "the form MyClass(int, float).");
125 };
126 
127 template <typename CandidateLambda>
128 struct NotALambdaError {
129   static_assert(AlwaysFalse<CandidateLambda>::value,
130                 "CandidateLambda was specified as parameter, but it's not a lambda.");
131 };
132 
133 template <typename Signature>
134 struct ConstructorDoesNotExistError {
135   static_assert(AlwaysFalse<Signature>::value, "The specified constructor does not exist.");
136 };
137 
138 template <typename I, typename C>
139 struct NotABaseClassOfError {
140   static_assert(AlwaysFalse<I>::value, "I is not a base class of C.");
141 };
142 
143 template <typename ProviderType>
144 struct FunctorUsedAsProviderError {
145   static_assert(AlwaysFalse<ProviderType>::value,
146                 "A stateful lambda or a non-lambda functor was used as provider. Only functions and stateless "
147                 "lambdas can be used as providers.");
148 };
149 
150 template <typename... ComponentRequirements>
151 struct ComponentWithRequirementsInInjectorError {
152   static_assert(AlwaysFalse<ComponentRequirements...>::value,
153                 "When using the two-argument constructor of Injector, the component used as second parameter "
154                 "must not have requirements (while the normalized component can), but the specified component "
155                 "requires ComponentRequirements.");
156 };
157 
158 template <typename... UnsatisfiedRequirements>
159 struct UnsatisfiedRequirementsInNormalizedComponentError {
160   static_assert(AlwaysFalse<UnsatisfiedRequirements...>::value,
161                 "The requirements in UnsatisfiedRequirements are required by the NormalizedComponent but are "
162                 "not provided by the Component (second parameter of the Injector constructor).");
163 };
164 
165 template <typename... TypesNotProvided>
166 struct TypesInInjectorNotProvidedError {
167   static_assert(AlwaysFalse<TypesNotProvided...>::value,
168                 "The types in TypesNotProvided are declared as provided by the injector, but none of the two "
169                 "components passed to the Injector constructor provides them.");
170 };
171 
172 template <typename... TypesProvidedAsConstOnly>
173 struct TypesInInjectorProvidedAsConstOnlyError {
174   static_assert(
175       AlwaysFalse<TypesProvidedAsConstOnly...>::value,
176       "The types in TypesProvidedAsConstOnly are declared as non-const provided types by the injector, but the "
177       "components passed to the Injector constructor provide them as const only. You should mark them as const in the "
178       "injector (e.g., switching from Injector<T> to Injector<const T>) or mark them as non-const in the "
179       "Component/NormalizedComponent (e.g. switching from [Normalized]Component<const T> to "
180       "[Normalized]Component<T>).");
181 };
182 
183 template <typename T>
184 struct TypeNotProvidedError {
185   static_assert(AlwaysFalse<T>::value,
186                 "Trying to get an instance of T, but it is not provided by this Provider/Injector.");
187 };
188 
189 template <typename T>
190 struct TypeProvidedAsConstOnlyError {
191   static_assert(
192       AlwaysFalse<T>::value,
193       "Trying to get an instance of T, but it is only provided as a constant by this Provider/Injector and a non-const "
194       "pointer/reference/Provider was requested. You should either switch to injecting a const value (e.g. switching "
195       "from"
196       " injecting T*, T&, std::unique_ptr<T> or Provider<T> to injecting a T, const T*, const T& or Provider<const T>) "
197       "or get the value from an Injector/Provider that provides it as a non-const type (e.g. switching from calling "
198       "get "
199       "on an Injector<const T> or on a Provider<const T> to calling get on an Injector<T> or a Provider<T>).");
200 };
201 
202 template <typename T>
203 struct NonConstBindingRequiredButConstBindingProvidedError {
204   static_assert(
205       AlwaysFalse<T>::value,
206       "The type T was provided as constant, however one of the constructors/providers/factories in this component "
207       "requires it as a non-constant (or this Component declares it as a non-const provided/required type). "
208       "If you want to only have a const binding for this type, you should change the places that use the type to "
209       "inject "
210       "a constant value (e.g. T, const T*, const T& and Provider<const T> are ok while you should avoid injecting T*, "
211       "T&,"
212       " std::unique_ptr<T> and Provider<T>) and if the type is in Component<...> make sure that it's marked as const "
213       "there"
214       " (e.g. Component<const T> and Component<Required<const T>> are ok while Component<T> and Component<Required<T>> "
215       "are "
216       "not. "
217       "On the other hand, if you want to have a non-const binding for this type, you should switch to a non-const "
218       "bindInstance (if you're binding an instance) or changing any installed component functions to declare the type "
219       "as "
220       "non-const, e.g. Component<T> or Component<Required<T>> instead of Component<const T> and "
221       "Component<Required<const T>>.");
222 };
223 
224 template <typename C, typename InjectSignature>
225 struct NoConstructorMatchingInjectSignatureError {
226   static_assert(AlwaysFalse<C>::value,
227                 "C contains an Inject typedef but it's not constructible with the specified types");
228 };
229 
230 template <typename ExpectedSignature, typename FunctorSignature>
231 struct FunctorSignatureDoesNotMatchError {
232   static_assert(AlwaysFalse<ExpectedSignature>::value,
233                 "Unexpected functor signature (it should be the same as ExpectedSignature minus any Assisted "
234                 "types).");
235 };
236 
237 template <typename Signature>
238 struct FactoryReturningPointerError {
239   static_assert(AlwaysFalse<Signature>::value,
240                 "The specified factory returns a pointer. This is not supported; return a value or an "
241                 "std::unique_ptr instead.");
242 };
243 
244 template <typename Lambda>
245 struct LambdaWithCapturesError {
246   // It's not guaranteed by the standard, but it's reasonable to expect lambdas with no captures
247   // to be empty. This is always the case in GCC and Clang, but is not guaranteed to work in all
248   // conforming C++ compilers. If this error happens for a lambda with no captures, please file a
249   // bug at https://github.com/google/fruit/issues and indicate the compiler (with version) that
250   // you're using.
251   static_assert(AlwaysFalse<Lambda>::value, "Only lambdas with no captures are supported.");
252 };
253 
254 template <typename Lambda>
255 struct NonTriviallyCopyableLambdaError {
256   // It's not guaranteed by the standard, but it's reasonable to expect lambdas with no captures
257   // to be trivially copyable. This is always the case in GCC and Clang, but is not guaranteed to
258   // work in all conforming C++ compilers. If this error happens for a lambda with no captures,
259   // please file a bug at https://github.com/google/fruit/issues and indicate the compiler (with
260   // version) that you're using.
261   static_assert(AlwaysFalse<Lambda>::value,
262                 "Only trivially copyable lambdas are supported. Make sure that your lambda has no captures.");
263 };
264 
265 template <typename C>
266 struct CannotConstructAbstractClassError {
267   static_assert(AlwaysFalse<C>::value, "The specified class can't be constructed because it's an abstract class.");
268 };
269 
270 template <typename C>
271 struct InterfaceBindingToSelfError {
272   static_assert(AlwaysFalse<C>::value,
273                 "The type C was bound to itself. If this was intentional, to \"tell Fruit to inject the type"
274                 " C\", this binding is unnecessary, just remove it. bind<I,C>() is to tell Fruit about"
275                 " base-derived class relationships.");
276 };
277 
278 template <typename TypeParameter, typename TypeOfValue>
279 struct TypeMismatchInBindInstanceError {
280   static_assert(AlwaysFalse<TypeParameter>::value,
281                 "A type parameter was specified in bindInstance() but it doesn't match the value type"
282                 " (even after removing the fruit::Annotation<>, if any). Please change the type parameter"
283                 " to be the same as the type of the value (or a subclass).");
284 };
285 
286 template <typename RequiredType>
287 struct RequiredTypesInComponentArgumentsError {
288   static_assert(AlwaysFalse<RequiredType>::value,
289                 "A Required<...> type was passed as a non-first template parameter to fruit::Component or "
290                 "fruit::NormalizedComponent. "
291                 "All required types (if any) should be passed together as a single Required<> type passed as the first "
292                 "type argument of fruit::Component (and fruit::NormalizedComponent). For example, write "
293                 "fruit::Component<fruit::Required<Foo, Bar>, Baz> instead of "
294                 "fruit::Component<fruit::Required<Foo>, fruit::Required<Bar>, Baz>.");
295 };
296 
297 template <typename T>
298 struct NonInjectableTypeError {
299   static_assert(
300       AlwaysFalse<T>::value,
301       "The type T is not injectable. Injectable types are of the form X, X*, X&, const X, const X*, const X&, "
302       "std::shared_ptr<X>, or Provider<X> where X is a fundamental type (excluding void), a class, a struct or "
303       "an enum.");
304 };
305 
306 template <typename T>
307 struct ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError {
308   static_assert(
309       AlwaysFalse<T>::value,
310       "The type T was declared as a const Required type in the returned Component, however a non-const binding is "
311       "required. You should either change all the usages of this type so that they no longer require a non-const "
312       "binding "
313       "(i.e., you shouldn't inject T*, T& or std::shared_ptr<T>) or you should remove the 'const' in the type of the "
314       "returned Component, e.g. changing fruit::Component<fruit::Required<const T, ...>, ...> to "
315       "fruit::Component<fruit::Required<T, ...>, ...>.");
316 };
317 
318 template <typename T>
319 struct ProviderReturningPointerToAbstractClassWithNoVirtualDestructorError {
320   static_assert(
321       AlwaysFalse<T>::value,
322       "registerProvider() was called with a lambda that returns a pointer to T, but T is an abstract class with no "
323       "virtual destructor so when the injector is deleted Fruit will be unable to call the right destructor (the one "
324       "of "
325       "the concrete class that was then casted to T). You must either add a virtual destructor to T or change the "
326       "registerProvider() call to return a pointer to the concrete class (and then add a bind<T, TImpl>() so that T is "
327       "bound).");
328 };
329 
330 template <typename T>
331 struct MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorError {
332   static_assert(
333       AlwaysFalse<T>::value,
334       "registerMultibindingProvider() was called with a lambda that returns a pointer to T, but T is an abstract class "
335       "with no virtual destructor so when the injector is deleted Fruit will be unable to call the right destructor "
336       "(the "
337       "one of the concrete class that was then casted to T). You must add a virtual destructor to T or replace the "
338       "registerMultibindingProvider() with a registerProvider() for the concrete class and an addMultibinding() for T. "
339       "Note that with the latter, if you end up with multiple addMultibinding() calls for the same concrete class, "
340       "there will be only one instance of the concrete class in the injector, not one per addMultibdinding() call; if "
341       "you want separate instances you might want to use annotated injection for the concrete class (so that there's "
342       "one "
343       "instance per annotation).");
344 };
345 
346 template <typename T>
347 struct RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorError {
348   static_assert(AlwaysFalse<T>::value,
349                 "registerFactory() was called with a lambda that returns a std::unique_ptr<T>, but T is an abstract "
350                 "class with no "
351                 "virtual destructor so when the returned std::unique_ptr<T> object is deleted the wrong destructor "
352                 "will be called "
353                 "(T's destructor instead of the one of the concrete class that was then casted to T). You must add a "
354                 "virtual destructor to T.");
355 };
356 
357 template <typename BaseFactory, typename DerivedFactory>
358 struct FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError {
359   static_assert(
360       AlwaysFalse<BaseFactory>::value,
361       "Fruit was trying to bind BaseFactory to DerivedFactory but the return type of BaseFactory is a std::unique_ptr "
362       "of "
363       "a class with no virtual destructor, so when the std::unique_ptr object is destroyed the wrong destructor would "
364       "be "
365       "called (the one in the base class instead of the derived class). To avoid this, you must add a virtual "
366       "destructor to the base class.");
367 };
368 
369 template <typename Arg>
370 struct IncorrectArgTypePassedToInstallComponentFuntionsError {
371     static_assert(
372         AlwaysFalse<Arg>::value,
373         "All arguments passed to installComponentFunctions() must be fruit::ComponentFunction<...> objects but an "
374         "argument with type Arg was passed instead.");
375 };
376 
377 struct LambdaWithCapturesErrorTag {
378   template <typename Lambda>
379   using apply = LambdaWithCapturesError<Lambda>;
380 };
381 
382 struct NonTriviallyCopyableLambdaErrorTag {
383   template <typename Lambda>
384   using apply = NonTriviallyCopyableLambdaError<Lambda>;
385 };
386 
387 struct FactoryReturningPointerErrorTag {
388   template <typename Signature>
389   using apply = FactoryReturningPointerError<Signature>;
390 };
391 
392 struct NoBindingFoundErrorTag {
393   template <typename T>
394   using apply = NoBindingFoundError<T>;
395 };
396 
397 struct RepeatedTypesErrorTag {
398   template <typename... Ts>
399   using apply = RepeatedTypesError<Ts...>;
400 };
401 
402 struct SelfLoopErrorTag {
403   template <typename... TypesInLoop>
404   using apply = SelfLoopError<TypesInLoop...>;
405 };
406 
407 struct NonClassTypeErrorTag {
408   template <typename T, typename C>
409   using apply = NonClassTypeError<T, C>;
410 };
411 
412 struct AnnotatedTypeErrorTag {
413   template <typename T, typename C>
414   using apply = AnnotatedTypeError<T, C>;
415 };
416 
417 struct TypeAlreadyBoundErrorTag {
418   template <typename C>
419   using apply = TypeAlreadyBoundError<C>;
420 };
421 
422 struct RequiredFactoryWithDifferentSignatureErrorTag {
423   template <typename RequiredSignature, typename SignatureInInjectTypedef>
424   using apply = RequiredFactoryWithDifferentSignatureError<RequiredSignature, SignatureInInjectTypedef>;
425 };
426 
427 struct AnnotatedSignatureDifferentFromLambdaSignatureErrorTag {
428   template <typename Signature, typename SignatureInLambda>
429   using apply = AnnotatedSignatureDifferentFromLambdaSignatureError<Signature, SignatureInLambda>;
430 };
431 
432 struct DuplicateTypesInComponentErrorTag {
433   template <typename... DuplicatedTypes>
434   using apply = DuplicateTypesInComponentError<DuplicatedTypes...>;
435 };
436 
437 struct InjectorWithRequirementsErrorTag {
438   template <typename... Requirements>
439   using apply = InjectorWithRequirementsError<Requirements...>;
440 };
441 
442 struct ComponentWithRequirementsInInjectorErrorTag {
443   template <typename... ComponentRequirements>
444   using apply = ComponentWithRequirementsInInjectorError<ComponentRequirements...>;
445 };
446 
447 struct InjectTypedefNotASignatureErrorTag {
448   template <typename C, typename TypeInInjectTypedef>
449   using apply = InjectTypedefNotASignatureError<C, TypeInInjectTypedef>;
450 };
451 
452 struct InjectTypedefForWrongClassErrorTag {
453   template <typename C, typename ReturnTypeOfInjectTypedef>
454   using apply = InjectTypedefForWrongClassError<C, ReturnTypeOfInjectTypedef>;
455 };
456 
457 struct InjectTypedefWithAnnotationErrorTag {
458   template <typename C>
459   using apply = InjectTypedefWithAnnotationError<C>;
460 };
461 
462 struct UnsatisfiedRequirementsInNormalizedComponentErrorTag {
463   template <typename... UnsatisfiedRequirements>
464   using apply = UnsatisfiedRequirementsInNormalizedComponentError<UnsatisfiedRequirements...>;
465 };
466 
467 struct TypesInInjectorNotProvidedErrorTag {
468   template <typename... TypesNotProvided>
469   using apply = TypesInInjectorNotProvidedError<TypesNotProvided...>;
470 };
471 
472 struct TypesInInjectorProvidedAsConstOnlyErrorTag {
473   template <typename... TypesProvidedAsConstOnly>
474   using apply = TypesInInjectorProvidedAsConstOnlyError<TypesProvidedAsConstOnly...>;
475 };
476 
477 struct FunctorUsedAsProviderErrorTag {
478   template <typename ProviderType>
479   using apply = FunctorUsedAsProviderError<ProviderType>;
480 };
481 
482 struct ConstructorDoesNotExistErrorTag {
483   template <typename Signature>
484   using apply = ConstructorDoesNotExistError<Signature>;
485 };
486 
487 struct NotABaseClassOfErrorTag {
488   template <typename I, typename C>
489   using apply = NotABaseClassOfError<I, C>;
490 };
491 
492 struct NotASignatureErrorTag {
493   template <typename CandidateSignature>
494   using apply = NotASignatureError<CandidateSignature>;
495 };
496 
497 struct NotALambdaErrorTag {
498   template <typename CandidateLambda>
499   using apply = NotALambdaError<CandidateLambda>;
500 };
501 
502 struct TypeNotProvidedErrorTag {
503   template <typename T>
504   using apply = TypeNotProvidedError<T>;
505 };
506 
507 struct TypeProvidedAsConstOnlyErrorTag {
508   template <typename T>
509   using apply = TypeProvidedAsConstOnlyError<T>;
510 };
511 
512 struct NonConstBindingRequiredButConstBindingProvidedErrorTag {
513   template <typename T>
514   using apply = NonConstBindingRequiredButConstBindingProvidedError<T>;
515 };
516 
517 struct NoConstructorMatchingInjectSignatureErrorTag {
518   template <typename C, typename InjectSignature>
519   using apply = NoConstructorMatchingInjectSignatureError<C, InjectSignature>;
520 };
521 
522 struct FunctorSignatureDoesNotMatchErrorTag {
523   template <typename ExpectedSignature, typename FunctorSignature>
524   using apply = FunctorSignatureDoesNotMatchError<ExpectedSignature, FunctorSignature>;
525 };
526 
527 struct CannotConstructAbstractClassErrorTag {
528   template <typename C>
529   using apply = CannotConstructAbstractClassError<C>;
530 };
531 
532 struct NoBindingFoundForAbstractClassErrorTag {
533   template <typename T, typename C>
534   using apply = NoBindingFoundForAbstractClassError<T, C>;
535 };
536 
537 struct InterfaceBindingToSelfErrorTag {
538   template <typename C>
539   using apply = InterfaceBindingToSelfError<C>;
540 };
541 
542 struct TypeMismatchInBindInstanceErrorTag {
543   template <typename TypeParameter, typename TypeOfValue>
544   using apply = TypeMismatchInBindInstanceError<TypeParameter, TypeOfValue>;
545 };
546 
547 struct RequiredTypesInComponentArgumentsErrorTag {
548   template <typename RequiredType>
549   using apply = RequiredTypesInComponentArgumentsError<RequiredType>;
550 };
551 
552 struct NonInjectableTypeErrorTag {
553   template <typename T>
554   using apply = NonInjectableTypeError<T>;
555 };
556 
557 struct ConstBindingDeclaredAsRequiredButNonConstBindingRequiredErrorTag {
558   template <typename T>
559   using apply = ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<T>;
560 };
561 
562 struct ProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag {
563   template <typename T>
564   using apply = ProviderReturningPointerToAbstractClassWithNoVirtualDestructorError<T>;
565 };
566 
567 struct MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag {
568   template <typename T>
569   using apply = MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorError<T>;
570 };
571 
572 struct RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorErrorTag {
573   template <typename T>
574   using apply = RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorError<T>;
575 };
576 
577 struct FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorErrorTag {
578   template <typename BaseFactory, typename DerivedFactory>
579   using apply = FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError<BaseFactory, DerivedFactory>;
580 };
581 
582 struct IncorrectArgTypePassedToInstallComponentFuntionsErrorTag {
583   template <typename Arg>
584   using apply = IncorrectArgTypePassedToInstallComponentFuntionsError<Arg>;
585 };
586 
587 } // namespace impl
588 } // namespace fruit
589 
590 #endif // FRUIT_INJECTION_ERRORS_H
591