aboutsummaryrefslogtreecommitdiff
path: root/include/fruit/impl/injection_errors.h
blob: 68247d2c1da9c2c5f198a9b64aa49c2e6458034b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef FRUIT_INJECTION_ERRORS_H
#define FRUIT_INJECTION_ERRORS_H

#include <fruit/impl/fruit_assert.h>
#include <fruit/impl/meta/set.h>

namespace fruit {
namespace impl {

template <typename... Ts>
struct AlwaysFalse {
  static constexpr bool value = false;
};

template <typename T>
struct NoBindingFoundError {
  static_assert(AlwaysFalse<T>::value, "No explicit binding nor C::Inject definition was found for T.");
};

template <typename T, typename C>
struct NoBindingFoundForAbstractClassError {
  static_assert(AlwaysFalse<T>::value,
                "No explicit binding was found for T, and note that C is an abstract class (so Fruit can't auto-inject "
                "this type, "
                "even if it has an Inject typedef or an INJECT annotation that will be ignored).");
};

template <typename... Ts>
struct RepeatedTypesError {
  static_assert(AlwaysFalse<Ts...>::value,
                "A type was specified more than once. Requirements and provided types should be unique.");
};

template <typename... TypesInLoop>
struct SelfLoopError {
  static_assert(AlwaysFalse<TypesInLoop...>::value,
                "Found a loop in the dependencies! The types in TypesInLoop all depend on the next, and the "
                "last one depends on the first.");
};

template <typename T, typename C>
struct NonClassTypeError {
  static_assert(AlwaysFalse<T>::value, "A non-class type T was specified. Use C instead.");
};

template <typename AnnotatedT, typename T>
struct AnnotatedTypeError {
  static_assert(AlwaysFalse<T>::value, "An annotated type was specified where a non-annotated type was expected.");
};

template <typename C>
struct TypeAlreadyBoundError {
  static_assert(AlwaysFalse<C>::value, "Trying to bind C but it is already bound.");
};

template <typename RequiredSignature, typename SignatureInInjectTypedef>
struct RequiredFactoryWithDifferentSignatureError {
  static_assert(AlwaysFalse<RequiredSignature>::value,
                "The required C factory doesn't have the same signature as the Inject annotation in C.");
};

template <typename Signature, typename SignatureInLambda>
struct AnnotatedSignatureDifferentFromLambdaSignatureError {
  static_assert(AlwaysFalse<Signature>::value,
                "The annotated signature specified is not the same as the lambda's signature (after removing "
                "annotations).");
};

template <typename... DuplicatedTypes>
struct DuplicateTypesInComponentError {
  static_assert(AlwaysFalse<DuplicatedTypes...>::value,
                "The installed component provides some types that are already provided by the current "
                "component.");
};

template <typename... Requirements>
struct InjectorWithRequirementsError {
  static_assert(AlwaysFalse<Requirements...>::value,
                "Injectors can't have requirements. If you want Fruit to try auto-resolving the requirements "
                "in the injector's scope, cast the component to a component with no requirements before "
                "constructing the injector with it.");
};

template <typename C, typename CandidateSignature>
struct InjectTypedefNotASignatureError {
  static_assert(AlwaysFalse<C>::value, "C::Inject should be a typedef to a signature, e.g. C(int)");
};

template <typename C, typename SignatureReturnType>
struct InjectTypedefForWrongClassError {
  static_assert(AlwaysFalse<C>::value,
                "C::Inject is a signature, but does not return a C. Maybe the class C has no Inject typedef "
                "and inherited the base class' one? If that's not the case, make sure it returns just C, not "
                "C* or other types.");
};

template <typename C>
struct InjectTypedefWithAnnotationError {
  static_assert(AlwaysFalse<C>::value,
                "C::Inject is a signature that returns an annotated type. The annotation must be removed, "
                "Fruit will deduce the correct annotation based on how the required binding.");
};

template <typename CandidateSignature>
struct NotASignatureError {
  static_assert(AlwaysFalse<CandidateSignature>::value,
                "CandidateSignature was specified as parameter, but it's not a signature. Signatures are of "
                "the form MyClass(int, float).");
};

template <typename CandidateSignature>
struct AssistedParamInRegisterConstructorSignatureError {
  static_assert(AlwaysFalse<CandidateSignature>::value,
                "CandidateSignature was used as signature for a registerConstructor() (explicit or implicit via the "
                "INJECT macro / Inject typedef) but it contains an assisted parameter. When using assisted parameters"
                "You need to inject a factory like std::function<std::unique_ptr<MyClass>(int, float)> instead of "
                "injecting MyClass directly. If you used an explicit registerConstructor(), you also need to switch "
                "that to registerFactory().");
};

template <typename CandidateLambda>
struct NotALambdaError {
  static_assert(AlwaysFalse<CandidateLambda>::value,
                "CandidateLambda was specified as parameter, but it's not a lambda.");
};

template <typename Signature>
struct ConstructorDoesNotExistError {
  static_assert(AlwaysFalse<Signature>::value, "The specified constructor does not exist.");
};

template <typename I, typename C>
struct NotABaseClassOfError {
  static_assert(AlwaysFalse<I>::value, "I is not a base class of C.");
};

template <typename ProviderType>
struct FunctorUsedAsProviderError {
  static_assert(AlwaysFalse<ProviderType>::value,
                "A stateful lambda or a non-lambda functor was used as provider. Only functions and stateless "
                "lambdas can be used as providers.");
};

template <typename... ComponentRequirements>
struct ComponentWithRequirementsInInjectorError {
  static_assert(AlwaysFalse<ComponentRequirements...>::value,
                "When using the two-argument constructor of Injector, the component used as second parameter "
                "must not have requirements (while the normalized component can), but the specified component "
                "requires ComponentRequirements.");
};

template <typename... UnsatisfiedRequirements>
struct UnsatisfiedRequirementsInNormalizedComponentError {
  static_assert(AlwaysFalse<UnsatisfiedRequirements...>::value,
                "The requirements in UnsatisfiedRequirements are required by the NormalizedComponent but are "
                "not provided by the Component (second parameter of the Injector constructor).");
};

template <typename... TypesNotProvided>
struct TypesInInjectorNotProvidedError {
  static_assert(AlwaysFalse<TypesNotProvided...>::value,
                "The types in TypesNotProvided are declared as provided by the injector, but none of the two "
                "components passed to the Injector constructor provides them.");
};

template <typename... TypesProvidedAsConstOnly>
struct TypesInInjectorProvidedAsConstOnlyError {
  static_assert(
      AlwaysFalse<TypesProvidedAsConstOnly...>::value,
      "The types in TypesProvidedAsConstOnly are declared as non-const provided types by the injector, but the "
      "components passed to the Injector constructor provide them as const only. You should mark them as const in the "
      "injector (e.g., switching from Injector<T> to Injector<const T>) or mark them as non-const in the "
      "Component/NormalizedComponent (e.g. switching from [Normalized]Component<const T> to "
      "[Normalized]Component<T>).");
};

template <typename T>
struct TypeNotProvidedError {
  static_assert(AlwaysFalse<T>::value,
                "Trying to get an instance of T, but it is not provided by this Provider/Injector.");
};

template <typename T>
struct TypeProvidedAsConstOnlyError {
  static_assert(
      AlwaysFalse<T>::value,
      "Trying to get an instance of T, but it is only provided as a constant by this Provider/Injector and a non-const "
      "pointer/reference/Provider was requested. You should either switch to injecting a const value (e.g. switching "
      "from"
      " injecting T*, T&, std::unique_ptr<T> or Provider<T> to injecting a T, const T*, const T& or Provider<const T>) "
      "or get the value from an Injector/Provider that provides it as a non-const type (e.g. switching from calling "
      "get "
      "on an Injector<const T> or on a Provider<const T> to calling get on an Injector<T> or a Provider<T>).");
};

template <typename T>
struct NonConstBindingRequiredButConstBindingProvidedError {
  static_assert(
      AlwaysFalse<T>::value,
      "The type T was provided as constant, however one of the constructors/providers/factories in this component "
      "requires it as a non-constant (or this Component declares it as a non-const provided/required type). "
      "If you want to only have a const binding for this type, you should change the places that use the type to "
      "inject "
      "a constant value (e.g. T, const T*, const T& and Provider<const T> are ok while you should avoid injecting T*, "
      "T&,"
      " std::unique_ptr<T> and Provider<T>) and if the type is in Component<...> make sure that it's marked as const "
      "there"
      " (e.g. Component<const T> and Component<Required<const T>> are ok while Component<T> and Component<Required<T>> "
      "are "
      "not. "
      "On the other hand, if you want to have a non-const binding for this type, you should switch to a non-const "
      "bindInstance (if you're binding an instance) or changing any installed component functions to declare the type "
      "as "
      "non-const, e.g. Component<T> or Component<Required<T>> instead of Component<const T> and "
      "Component<Required<const T>>.");
};

template <typename C, typename InjectSignature>
struct NoConstructorMatchingInjectSignatureError {
  static_assert(AlwaysFalse<C>::value,
                "C contains an Inject typedef but it's not constructible with the specified types");
};

template <typename ExpectedSignature, typename FunctorSignature>
struct FunctorSignatureDoesNotMatchError {
  static_assert(AlwaysFalse<ExpectedSignature>::value,
                "Unexpected functor signature (it should be the same as ExpectedSignature minus any Assisted "
                "types).");
};

template <typename Signature>
struct FactoryReturningPointerError {
  static_assert(AlwaysFalse<Signature>::value,
                "The specified factory returns a pointer. This is not supported; return a value or an "
                "std::unique_ptr instead.");
};

template <typename Lambda>
struct LambdaWithCapturesError {
  // It's not guaranteed by the standard, but it's reasonable to expect lambdas with no captures
  // to be empty. This is always the case in GCC and Clang, but is not guaranteed to work in all
  // conforming C++ compilers. If this error happens for a lambda with no captures, please file a
  // bug at https://github.com/google/fruit/issues and indicate the compiler (with version) that
  // you're using.
  static_assert(AlwaysFalse<Lambda>::value, "Only lambdas with no captures are supported.");
};

template <typename Lambda>
struct NonTriviallyCopyableLambdaError {
  // It's not guaranteed by the standard, but it's reasonable to expect lambdas with no captures
  // to be trivially copyable. This is always the case in GCC and Clang, but is not guaranteed to
  // work in all conforming C++ compilers. If this error happens for a lambda with no captures,
  // please file a bug at https://github.com/google/fruit/issues and indicate the compiler (with
  // version) that you're using.
  static_assert(AlwaysFalse<Lambda>::value,
                "Only trivially copyable lambdas are supported. Make sure that your lambda has no captures.");
};

template <typename C>
struct CannotConstructAbstractClassError {
  static_assert(AlwaysFalse<C>::value, "The specified class can't be constructed because it's an abstract class.");
};

template <typename C>
struct InterfaceBindingToSelfError {
  static_assert(AlwaysFalse<C>::value,
                "The type C was bound to itself. If this was intentional, to \"tell Fruit to inject the type"
                " C\", this binding is unnecessary, just remove it. bind<I,C>() is to tell Fruit about"
                " base-derived class relationships.");
};

template <typename TypeParameter, typename TypeOfValue>
struct TypeMismatchInBindInstanceError {
  static_assert(AlwaysFalse<TypeParameter>::value,
                "A type parameter was specified in bindInstance() but it doesn't match the value type"
                " (even after removing the fruit::Annotation<>, if any). Please change the type parameter"
                " to be the same as the type of the value (or a subclass).");
};

template <typename RequiredType>
struct RequiredTypesInComponentArgumentsError {
  static_assert(AlwaysFalse<RequiredType>::value,
                "A Required<...> type was passed as a non-first template parameter to fruit::Component or "
                "fruit::NormalizedComponent. "
                "All required types (if any) should be passed together as a single Required<> type passed as the first "
                "type argument of fruit::Component (and fruit::NormalizedComponent). For example, write "
                "fruit::Component<fruit::Required<Foo, Bar>, Baz> instead of "
                "fruit::Component<fruit::Required<Foo>, fruit::Required<Bar>, Baz>.");
};

template <typename T>
struct NonInjectableTypeError {
  static_assert(
      AlwaysFalse<T>::value,
      "The type T is not injectable. Injectable types are of the form X, X*, X&, const X, const X*, const X&, "
      "std::shared_ptr<X>, or Provider<X> where X is a fundamental type (excluding void), a class, a struct or "
      "an enum.");
};

template <typename T>
struct ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError {
  static_assert(
      AlwaysFalse<T>::value,
      "The type T was declared as a const Required type in the returned Component, however a non-const binding is "
      "required. You should either change all the usages of this type so that they no longer require a non-const "
      "binding "
      "(i.e., you shouldn't inject T*, T& or std::shared_ptr<T>) or you should remove the 'const' in the type of the "
      "returned Component, e.g. changing fruit::Component<fruit::Required<const T, ...>, ...> to "
      "fruit::Component<fruit::Required<T, ...>, ...>.");
};

template <typename T>
struct ProviderReturningPointerToAbstractClassWithNoVirtualDestructorError {
  static_assert(
      AlwaysFalse<T>::value,
      "registerProvider() was called with a lambda that returns a pointer to T, but T is an abstract class with no "
      "virtual destructor so when the injector is deleted Fruit will be unable to call the right destructor (the one "
      "of "
      "the concrete class that was then casted to T). You must either add a virtual destructor to T or change the "
      "registerProvider() call to return a pointer to the concrete class (and then add a bind<T, TImpl>() so that T is "
      "bound).");
};

template <typename T>
struct MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorError {
  static_assert(
      AlwaysFalse<T>::value,
      "registerMultibindingProvider() was called with a lambda that returns a pointer to T, but T is an abstract class "
      "with no virtual destructor so when the injector is deleted Fruit will be unable to call the right destructor "
      "(the "
      "one of the concrete class that was then casted to T). You must add a virtual destructor to T or replace the "
      "registerMultibindingProvider() with a registerProvider() for the concrete class and an addMultibinding() for T. "
      "Note that with the latter, if you end up with multiple addMultibinding() calls for the same concrete class, "
      "there will be only one instance of the concrete class in the injector, not one per addMultibdinding() call; if "
      "you want separate instances you might want to use annotated injection for the concrete class (so that there's "
      "one "
      "instance per annotation).");
};

template <typename T>
struct RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorError {
  static_assert(AlwaysFalse<T>::value,
                "registerFactory() was called with a lambda that returns a std::unique_ptr<T>, but T is an abstract "
                "class with no "
                "virtual destructor so when the returned std::unique_ptr<T> object is deleted the wrong destructor "
                "will be called "
                "(T's destructor instead of the one of the concrete class that was then casted to T). You must add a "
                "virtual destructor to T.");
};

template <typename BaseFactory, typename DerivedFactory>
struct FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError {
  static_assert(
      AlwaysFalse<BaseFactory>::value,
      "Fruit was trying to bind BaseFactory to DerivedFactory but the return type of BaseFactory is a std::unique_ptr "
      "of "
      "a class with no virtual destructor, so when the std::unique_ptr object is destroyed the wrong destructor would "
      "be "
      "called (the one in the base class instead of the derived class). To avoid this, you must add a virtual "
      "destructor to the base class.");
};

template <typename Arg>
struct IncorrectArgTypePassedToInstallComponentFuntionsError {
    static_assert(
        AlwaysFalse<Arg>::value,
        "All arguments passed to installComponentFunctions() must be fruit::ComponentFunction<...> objects but an "
        "argument with type Arg was passed instead.");
};

struct LambdaWithCapturesErrorTag {
  template <typename Lambda>
  using apply = LambdaWithCapturesError<Lambda>;
};

struct NonTriviallyCopyableLambdaErrorTag {
  template <typename Lambda>
  using apply = NonTriviallyCopyableLambdaError<Lambda>;
};

struct FactoryReturningPointerErrorTag {
  template <typename Signature>
  using apply = FactoryReturningPointerError<Signature>;
};

struct NoBindingFoundErrorTag {
  template <typename T>
  using apply = NoBindingFoundError<T>;
};

struct RepeatedTypesErrorTag {
  template <typename... Ts>
  using apply = RepeatedTypesError<Ts...>;
};

struct SelfLoopErrorTag {
  template <typename... TypesInLoop>
  using apply = SelfLoopError<TypesInLoop...>;
};

struct NonClassTypeErrorTag {
  template <typename T, typename C>
  using apply = NonClassTypeError<T, C>;
};

struct AnnotatedTypeErrorTag {
  template <typename T, typename C>
  using apply = AnnotatedTypeError<T, C>;
};

struct TypeAlreadyBoundErrorTag {
  template <typename C>
  using apply = TypeAlreadyBoundError<C>;
};

struct RequiredFactoryWithDifferentSignatureErrorTag {
  template <typename RequiredSignature, typename SignatureInInjectTypedef>
  using apply = RequiredFactoryWithDifferentSignatureError<RequiredSignature, SignatureInInjectTypedef>;
};

struct AnnotatedSignatureDifferentFromLambdaSignatureErrorTag {
  template <typename Signature, typename SignatureInLambda>
  using apply = AnnotatedSignatureDifferentFromLambdaSignatureError<Signature, SignatureInLambda>;
};

struct DuplicateTypesInComponentErrorTag {
  template <typename... DuplicatedTypes>
  using apply = DuplicateTypesInComponentError<DuplicatedTypes...>;
};

struct InjectorWithRequirementsErrorTag {
  template <typename... Requirements>
  using apply = InjectorWithRequirementsError<Requirements...>;
};

struct ComponentWithRequirementsInInjectorErrorTag {
  template <typename... ComponentRequirements>
  using apply = ComponentWithRequirementsInInjectorError<ComponentRequirements...>;
};

struct InjectTypedefNotASignatureErrorTag {
  template <typename C, typename TypeInInjectTypedef>
  using apply = InjectTypedefNotASignatureError<C, TypeInInjectTypedef>;
};

struct InjectTypedefForWrongClassErrorTag {
  template <typename C, typename ReturnTypeOfInjectTypedef>
  using apply = InjectTypedefForWrongClassError<C, ReturnTypeOfInjectTypedef>;
};

struct InjectTypedefWithAnnotationErrorTag {
  template <typename C>
  using apply = InjectTypedefWithAnnotationError<C>;
};

struct UnsatisfiedRequirementsInNormalizedComponentErrorTag {
  template <typename... UnsatisfiedRequirements>
  using apply = UnsatisfiedRequirementsInNormalizedComponentError<UnsatisfiedRequirements...>;
};

struct TypesInInjectorNotProvidedErrorTag {
  template <typename... TypesNotProvided>
  using apply = TypesInInjectorNotProvidedError<TypesNotProvided...>;
};

struct TypesInInjectorProvidedAsConstOnlyErrorTag {
  template <typename... TypesProvidedAsConstOnly>
  using apply = TypesInInjectorProvidedAsConstOnlyError<TypesProvidedAsConstOnly...>;
};

struct FunctorUsedAsProviderErrorTag {
  template <typename ProviderType>
  using apply = FunctorUsedAsProviderError<ProviderType>;
};

struct ConstructorDoesNotExistErrorTag {
  template <typename Signature>
  using apply = ConstructorDoesNotExistError<Signature>;
};

struct NotABaseClassOfErrorTag {
  template <typename I, typename C>
  using apply = NotABaseClassOfError<I, C>;
};

struct NotASignatureErrorTag {
  template <typename CandidateSignature>
  using apply = NotASignatureError<CandidateSignature>;
};

struct AssistedParamInRegisterConstructorSignatureErrorTag {
  template <typename CandidateSignature>
  using apply = AssistedParamInRegisterConstructorSignatureError<CandidateSignature>;
};

struct NotALambdaErrorTag {
  template <typename CandidateLambda>
  using apply = NotALambdaError<CandidateLambda>;
};

struct TypeNotProvidedErrorTag {
  template <typename T>
  using apply = TypeNotProvidedError<T>;
};

struct TypeProvidedAsConstOnlyErrorTag {
  template <typename T>
  using apply = TypeProvidedAsConstOnlyError<T>;
};

struct NonConstBindingRequiredButConstBindingProvidedErrorTag {
  template <typename T>
  using apply = NonConstBindingRequiredButConstBindingProvidedError<T>;
};

struct NoConstructorMatchingInjectSignatureErrorTag {
  template <typename C, typename InjectSignature>
  using apply = NoConstructorMatchingInjectSignatureError<C, InjectSignature>;
};

struct FunctorSignatureDoesNotMatchErrorTag {
  template <typename ExpectedSignature, typename FunctorSignature>
  using apply = FunctorSignatureDoesNotMatchError<ExpectedSignature, FunctorSignature>;
};

struct CannotConstructAbstractClassErrorTag {
  template <typename C>
  using apply = CannotConstructAbstractClassError<C>;
};

struct NoBindingFoundForAbstractClassErrorTag {
  template <typename T, typename C>
  using apply = NoBindingFoundForAbstractClassError<T, C>;
};

struct InterfaceBindingToSelfErrorTag {
  template <typename C>
  using apply = InterfaceBindingToSelfError<C>;
};

struct TypeMismatchInBindInstanceErrorTag {
  template <typename TypeParameter, typename TypeOfValue>
  using apply = TypeMismatchInBindInstanceError<TypeParameter, TypeOfValue>;
};

struct RequiredTypesInComponentArgumentsErrorTag {
  template <typename RequiredType>
  using apply = RequiredTypesInComponentArgumentsError<RequiredType>;
};

struct NonInjectableTypeErrorTag {
  template <typename T>
  using apply = NonInjectableTypeError<T>;
};

struct ConstBindingDeclaredAsRequiredButNonConstBindingRequiredErrorTag {
  template <typename T>
  using apply = ConstBindingDeclaredAsRequiredButNonConstBindingRequiredError<T>;
};

struct ProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag {
  template <typename T>
  using apply = ProviderReturningPointerToAbstractClassWithNoVirtualDestructorError<T>;
};

struct MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorErrorTag {
  template <typename T>
  using apply = MultibindingProviderReturningPointerToAbstractClassWithNoVirtualDestructorError<T>;
};

struct RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorErrorTag {
  template <typename T>
  using apply = RegisterFactoryForUniquePtrOfAbstractClassWithNoVirtualDestructorError<T>;
};

struct FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorErrorTag {
  template <typename BaseFactory, typename DerivedFactory>
  using apply = FactoryBindingForUniquePtrOfClassWithNoVirtualDestructorError<BaseFactory, DerivedFactory>;
};

struct IncorrectArgTypePassedToInstallComponentFuntionsErrorTag {
  template <typename Arg>
  using apply = IncorrectArgTypePassedToInstallComponentFuntionsError<Arg>;
};

} // namespace impl
} // namespace fruit

#endif // FRUIT_INJECTION_ERRORS_H