blob: ef2bbb8251d92a6d7a357f8c32e76508dd091219 [file] [log] [blame]
Marco Poletticf798fa2014-06-21 15:05:15 +01001/*
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
Marco Polettia5289cf2015-03-15 10:42:03 +000020// This include is not required here, but having it here shortens the include trace in error messages.
21#include "impl/injection_errors.h"
22
Marco Poletti97e36232014-08-24 10:55:28 +020023#include "fruit_forward_decls.h"
24
Marco Poletticf798fa2014-06-21 15:05:15 +010025/**
26 * A convenience macro to define the Inject typedef while declaring/defining
27 * the constructor that will be used for injection.
Marco Poletti31f638a2015-05-10 21:21:25 +010028 * It also supports assisted injection and injection of annotated types.
Marco Poletticf798fa2014-06-21 15:05:15 +010029 *
30 * Example usage:
31 *
Marco Polettia1e99582014-11-09 10:00:47 +000032 * class MyClass {
Marco Poletticf798fa2014-06-21 15:05:15 +010033 * public:
Marco Polettia1e99582014-11-09 10:00:47 +000034 * INJECT(MyClass(Foo* foo, Bar* bar)) {...}
Marco Poletticf798fa2014-06-21 15:05:15 +010035 * };
36 *
37 * is equivalent to:
38 *
Marco Polettia1e99582014-11-09 10:00:47 +000039 * class MyClass {
Marco Poletticf798fa2014-06-21 15:05:15 +010040 * public:
Marco Polettia1e99582014-11-09 10:00:47 +000041 * using Inject = MyClass(Foo*, Bar*>);
Marco Poletticf798fa2014-06-21 15:05:15 +010042 *
Marco Polettia1e99582014-11-09 10:00:47 +000043 * 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) {...}
Marco Poletticf798fa2014-06-21 15:05:15 +010060 * };
61 *
Marco Poletti31f638a2015-05-10 21:21:25 +010062 * Example usage for annotated types (both the result type and parameters can be annotated
63 * independently):
64 *
65 * class MyClass {
66 * public:
67 * INJECT(ANNOTATED(MyAnnotation, MyClass)(ANNOTATED(SomeOtherAnnotation, Foo*) foo, Bar* bar)) {...}
68 * };
69 *
70 * ASSISTED and ANNOTATED *can* be used together in the same INJECT() annotation, but they can't both be used for a single
71 * parameter (as this wouldn't make sense, parameters that use assisted injection are user-supplied, they aren't injected
72 * from a binding).
73 *
Marco Polettic7b04102014-07-27 11:59:16 +010074 * NOTE: This can't be used if the constructor is templated (the class can be templated, however), if there are any default
75 * arguments or if the constructor is marked `explicit'.
Marco Polettia185d5e2014-11-08 09:00:35 +000076 * In those cases, define the Inject annotation manually or use registerConstructor()/registerFactory() instead.
Marco Poletticf798fa2014-06-21 15:05:15 +010077 *
Marco Polettia185d5e2014-11-08 09:00:35 +000078 * NOTE: ASSISTED takes just one argument, but it's declared as variadic to make sure that the preprocessor doesn't choke on
79 * multi-argument templates like the map above, that the processor is unable to parse correctly.
Marco Poletticf798fa2014-06-21 15:05:15 +010080 *
Marco Poletti31f638a2015-05-10 21:21:25 +010081 * NOTE: ASSISTED takes just 2 arguments, but it's declared as variadic to make sure that the preprocessor doesn't choke on
82 * multi-argument templates, that the processor is unable to parse correctly.
83 *
84 * NOTE: In addition to the public Inject typedef, two private typedefs (FruitAssistedTypedef and FruitAnnotatedTypedef) will be defined inside the class,
Marco Polettia185d5e2014-11-08 09:00:35 +000085 * make sure you don't define another typedef/field/method with the same name if you use the INJECT macro (unlikely but possible).
Marco Poletticf798fa2014-06-21 15:05:15 +010086 */
87#define INJECT(Signature) \
88using Inject = Signature; \
89private: \
90template <typename FruitAssistedDeclarationParam> \
Marco Poletti31f638a2015-05-10 21:21:25 +010091using FruitAssistedTypedef = FruitAssistedDeclarationParam; \
92template <typename FruitAnnotatedDeclarationParam> \
93using FruitAnnotatedTypedef = FruitAnnotatedDeclarationParam; \
Marco Poletticf798fa2014-06-21 15:05:15 +010094public: \
95Signature
96
Marco Poletti31f638a2015-05-10 21:21:25 +010097#define ASSISTED(...) FruitAssistedTypedef<__VA_ARGS__>
98#define ANNOTATED(Annotation, ...) FruitAnnotatedTypedef<Annotation, __VA_ARGS__>
Marco Poletticf798fa2014-06-21 15:05:15 +010099
Marco Poletti5bc98762014-07-27 11:02:44 +0100100/**
Marco Poletti31f638a2015-05-10 21:21:25 +0100101 * These are intentionally NOT in the fruit namespace, they can't be there for technical reasons.
Marco Poletticf798fa2014-06-21 15:05:15 +0100102 *
Marco Poletti31f638a2015-05-10 21:21:25 +0100103 * NOTE: don't use these directly, they're only used to implement the INJECT macro.
104 * Consider them part of fruit::impl.
Marco Poletticf798fa2014-06-21 15:05:15 +0100105 */
106template <typename T>
Marco Poletti31f638a2015-05-10 21:21:25 +0100107using FruitAssistedTypedef = fruit::Assisted<T>;
108template <typename Annotation, typename T>
109using FruitAnnotatedTypedef = fruit::Annotated<Annotation, T>;
Marco Poletticf798fa2014-06-21 15:05:15 +0100110
Marco Polettie0808b52014-08-23 16:59:13 +0200111#endif // FRUIT_MACRO_H