• 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_PROVIDER_H
18 #define FRUIT_PROVIDER_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/component.h>
24 
25 namespace fruit {
26 
27 /**
28  * A Provider is a class that allows access to instances of the types used as parameters of the Provider template.
29  * It's possible to inject a Provider<MyClass> instead of MyClass itself, and this allows lazy injection.
30  * For example:
31  *
32  * class S {
33  * private:
34  *   Bar* bar = nullptr;
35  *
36  * public:
37  *   INJECT(S(Foo* foo, Provider<Bar> barProvider)) {
38  *     if (foo->needsBar()) {
39  *       bar = barProvider.get();
40  *     }
41  *   }
42  * };
43  *
44  * In the example above, Bar will only be created if get<Bar*> is called.
45  * This can be useful if Bar is expensive to create (or some other types that need to be injected when a Bar is injected
46  * are) or if there are other side effects of the Bar constructor that are undesirable when !foo->needsBar().
47  * It's also possible to store the Provider object in a field, and create the Bar instance when the first method that
48  * needs it is called:
49  *
50  * class S {
51  * private:
52  *   Provider<Bar> barProvider;
53  *
54  * public:
55  *   INJECT(S(Provider<Bar> barProvider))
56  *   : barProvider(barProvider) {
57  *   }
58  *
59  *   void execute() {
60  *     if (...) {
61  *       Bar* bar = barProvider.get();
62  *       ...
63  *     }
64  *   }
65  * };
66  *
67  * As usual, Fruit ensures that (at most) one instance is ever created in a given injector; so if the Bar object was
68  * already constructed, the get() will simply return it.
69  *
70  * Note that you can inject a Provider<Foo> whenever you could have injected a Foo.
71  * It doesn't matter if Foo was bound using PartialComponent::registerProvider() or not.
72  */
73 template <typename C>
74 class Provider {
75 private:
76   using Check1 =
77       typename fruit::impl::meta::CheckIfError<fruit::impl::meta::Eval<fruit::impl::meta::CheckNormalizedTypes(
78           fruit::impl::meta::RemoveConstFromTypes(fruit::impl::meta::Vector<fruit::impl::meta::Type<C>>))>>::type;
79   // Force instantiation of Check1.
80   static_assert(true || sizeof(Check1), "");
81 
82   using Check2 =
83       typename fruit::impl::meta::CheckIfError<fruit::impl::meta::Eval<fruit::impl::meta::CheckNotAnnotatedTypes(
84           fruit::impl::meta::Vector<fruit::impl::meta::Type<C>>)>>::type;
85   // Force instantiation of Check2.
86   static_assert(true || sizeof(Check2), "");
87 
88 public:
89   /**
90    * Returns an instance of the specified type. The following variations are allowed:
91    *
92    * On a Provider<Foo>, you can call:
93    *
94    * - provider.get<Foo>()
95    * - provider.get<Foo*>()
96    * - provider.get<Foo&>()
97    * - provider.get<const Foo*>()
98    * - provider.get<const Foo&>()
99    * - provider.get<std::shared_ptr<Foo>>()
100    * - provider.get<Provider<Foo>>()
101    * - provider.get<Provider<const Foo>>()
102    *
103    * On a Provider<const Foo>, you can call:
104    *
105    * - provider.get<Foo>()
106    * - provider.get<const Foo*>()
107    * - provider.get<const Foo&>()
108    * - provider.get<Provider<const Foo>>()
109    *
110    * The shared_ptr version is slightly slower than the ones returning a reference/pointer, use those if possible.
111    *
112    * Calling get<> repeatedly for the same class with the same injector will return the same instance (except for the
113    * first variation above, that returns a value; in that case, another copy of the same instance will be returned).
114    */
115   template <typename T>
116   T get();
117 
118   /**
119    * This is a convenient way to call get(). E.g.:
120    *
121    * C& x(provider);
122    *
123    * is equivalent to:
124    *
125    * C& x = provider.get<C&>();
126    */
127   template <typename T>
128   explicit operator T();
129 
130   /**
131    * This is equivalent to get<C*>(), it's provided for convenience.
132    */
133   C* get();
134 
135 private:
136   // This is NOT owned by the provider object. It is not deleted on destruction.
137   // This is never nullptr.
138   fruit::impl::InjectorStorage* storage;
139   fruit::impl::InjectorStorage::Graph::node_iterator itr;
140 
141   Provider(fruit::impl::InjectorStorage* storage, fruit::impl::InjectorStorage::Graph::node_iterator itr);
142 
143   friend class fruit::impl::InjectorStorage;
144 
145   template <typename T>
146   friend struct fruit::impl::GetFirstStage;
147 
148   template <typename... OtherPs>
149   friend class Injector;
150 };
151 
152 } // namespace fruit
153 
154 #include <fruit/impl/provider.defn.h>
155 
156 #endif // FRUIT_PROVIDER_H
157