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_MACRO_H 18 #define FRUIT_MACRO_H 19 20 // This include is not required here, but having it here shortens the include trace in error messages. 21 #include <fruit/impl/injection_errors.h> 22 23 #include <fruit/fruit_forward_decls.h> 24 25 /** 26 * A convenience macro to define the Inject typedef while declaring/defining the constructor that will be used for 27 * injection. 28 * It also supports assisted injection and injection of annotated types. 29 * 30 * Example usage: 31 * 32 * class MyClass { 33 * public: 34 * INJECT(MyClass(Foo* foo, Bar* bar)) {...} 35 * }; 36 * 37 * is equivalent to: 38 * 39 * class MyClass { 40 * public: 41 * using Inject = MyClass(Foo*, Bar*); 42 * 43 * MyClass(Foo* foo, Bar* y) {...} 44 * }; 45 * 46 * Example usage for assisted injection (see PartialComponent::registerFactory): 47 * 48 * class MyClass { 49 * public: 50 * INJECT(MyClass(Foo* foo, ASSISTED(int) n) {...} 51 * }; 52 * 53 * is equivalent to: 54 * 55 * class MyClass { 56 * public: 57 * using Inject = MyClass(Foo*, Assisted<int>); 58 * 59 * MyClass(Foo* foo, int n) {...} 60 * }; 61 * 62 * Example usage for annotated types: 63 * 64 * class MyClass { 65 * public: 66 * INJECT(MyClass(ANNOTATED(SomeAnnotation, Foo*) foo, Bar* bar)) {...} 67 * }; 68 * 69 * ASSISTED and ANNOTATED *can* be used together in the same INJECT() annotation, but they can't both be used for a 70 * single parameter (as this wouldn't make sense, parameters that use assisted injection are user-supplied, they aren't 71 * injected from a binding). 72 * 73 * NOTE: This can't be used if the constructor is templated (the class can be templated, however), if there are any 74 * default arguments or if the constructor is marked `explicit'. 75 * In those cases, define the Inject annotation manually or use registerConstructor()/registerFactory() instead. 76 * 77 * NOTE: ASSISTED takes just one argument, but it's declared as variadic to make sure that the preprocessor doesn't 78 * choke on multi-argument templates like the map above, that the processor is unable to parse correctly. 79 * 80 * NOTE: ASSISTED takes just 2 arguments, but it's declared as variadic to make sure that the preprocessor doesn't choke 81 * on multi-argument templates, that the processor is unable to parse correctly. 82 * 83 * NOTE: In addition to the public Inject typedef, two typedefs (FruitAssistedTypedef and FruitAnnotatedTypedef) will be 84 * defined inside the class, make sure you don't define another typedef/field/method with the same name if you use the 85 * INJECT macro (unlikely but possible) these typedefs are an implementation detail of Fruit and should not be used. 86 * 87 * NOTE: The return type (MyClass in this case) should not be annotated. However an annotated 88 * MyClass (or MyClass factory) can be injected from any INJECT declaration. 89 */ 90 #define INJECT(Signature) \ 91 using Inject = Signature; \ 92 \ 93 template <typename FruitAssistedDeclarationParam> \ 94 using FruitAssistedTypedef = FruitAssistedDeclarationParam; \ 95 template <typename Annotation, typename FruitAnnotatedDeclarationParam> \ 96 using FruitAnnotatedTypedef = FruitAnnotatedDeclarationParam; \ 97 \ 98 Signature 99 100 #define ASSISTED(...) FruitAssistedTypedef<__VA_ARGS__> 101 #define ANNOTATED(Annotation, ...) FruitAnnotatedTypedef<Annotation, __VA_ARGS__> 102 103 /** 104 * These are intentionally NOT in the fruit namespace, they can't be there for technical reasons. 105 * 106 * NOTE: don't use these directly, they're only used to implement the INJECT macro. 107 * Consider them part of fruit::impl. 108 */ 109 template <typename T> 110 using FruitAssistedTypedef = fruit::Assisted<T>; 111 template <typename Annotation, typename T> 112 using FruitAnnotatedTypedef = fruit::Annotated<Annotation, T>; 113 114 #endif // FRUIT_MACRO_H 115