Home | History | Annotate | Download | only in fruit
      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