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