Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 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_COMPONENT_FUNCTORS_DEFN_H |
| 18 | #define FRUIT_COMPONENT_FUNCTORS_DEFN_H |
| 19 | |
Marco Poletti | f289510 | 2016-01-30 13:38:37 +0000 | [diff] [blame] | 20 | #include <fruit/component.h> |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 21 | |
Marco Poletti | f289510 | 2016-01-30 13:38:37 +0000 | [diff] [blame] | 22 | #include <fruit/impl/injection_errors.h> |
| 23 | #include <fruit/impl/injection_debug_errors.h> |
| 24 | #include <fruit/impl/storage/component_storage.h> |
Marco Poletti | 3e576c2 | 2016-06-19 16:34:08 +0100 | [diff] [blame] | 25 | #include <fruit/impl/storage/injector_storage.h> |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 26 | |
| 27 | #include <memory> |
| 28 | |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 29 | /********************************************************************************************************************************* |
| 30 | This file contains functors that take a Comp and return a struct Op with the form: |
| 31 | struct { |
| 32 | using Result = Comp1; |
| 33 | void operator()(ComponentStorage& storage) {...} |
| 34 | } |
| 35 | *********************************************************************************************************************************/ |
| 36 | |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 37 | namespace fruit { |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 38 | namespace impl { |
Marco Poletti | a19fd1e | 2015-03-07 18:50:37 +0000 | [diff] [blame] | 39 | namespace meta { |
| 40 | |
| 41 | struct GetResult { |
| 42 | template <typename F> |
| 43 | struct apply { |
| 44 | using type = typename F::Result; |
| 45 | }; |
| 46 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 47 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 48 | // Call(ComponentFunctor(F, Args...), Comp) |
| 49 | // is equivalent to: |
| 50 | // F(Comp, Args...) |
| 51 | struct ComponentFunctor { |
| 52 | template <typename F, typename... Args> |
| 53 | struct apply { |
| 54 | struct type { |
| 55 | template <typename Comp> |
| 56 | struct apply { |
| 57 | using type = F(Comp, Args...); |
| 58 | }; |
| 59 | }; |
| 60 | }; |
| 61 | }; |
| 62 | |
Marco Poletti | 1ff06b3 | 2015-07-19 20:06:19 +0100 | [diff] [blame] | 63 | struct NoOpComponentFunctor { |
| 64 | using Result = void; |
| 65 | template <typename... Types> |
| 66 | void operator()(ComponentStorage&, const Types&...) {} |
| 67 | }; |
| 68 | |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 69 | struct ComponentFunctorIdentity { |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 70 | template <typename Comp> |
| 71 | struct apply { |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 72 | struct type { |
| 73 | using Result = Comp; |
Marco Poletti | a19fd1e | 2015-03-07 18:50:37 +0000 | [diff] [blame] | 74 | void operator()(ComponentStorage&) {} |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 75 | }; |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 76 | }; |
| 77 | }; |
| 78 | |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 79 | struct Compose2ComponentFunctors { |
| 80 | template <typename F1, typename F2> |
| 81 | struct apply { |
| 82 | struct type { |
| 83 | template <typename Comp> |
| 84 | struct apply { |
| 85 | using Op1 = F1(Comp); |
| 86 | using Op2 = F2(GetResult(Op1)); |
| 87 | struct Op { |
| 88 | using Result = Eval<GetResult(Op2)>; |
| 89 | void operator()(ComponentStorage& storage) { |
| 90 | Eval<Op1>()(storage); |
| 91 | Eval<Op2>()(storage); |
| 92 | } |
| 93 | }; |
| 94 | using type = PropagateError(Op1, |
| 95 | PropagateError(Op2, |
| 96 | Op)); |
| 97 | }; |
| 98 | }; |
| 99 | }; |
| 100 | }; |
| 101 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 102 | // ComposeFunctors(F1,..,Fn) returns a functor that executes F1,..,Fn in order (stopping at the |
| 103 | // first Error). |
| 104 | struct ComposeFunctors { |
| 105 | template <typename... Functors> |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 106 | struct apply { |
| 107 | using type = Fold(Compose2ComponentFunctors, ComponentFunctorIdentity, Functors...); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 108 | }; |
| 109 | }; |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 110 | |
Marco Poletti | e844355 | 2016-02-07 10:25:39 +0000 | [diff] [blame] | 111 | // ReverseComposeFunctors(T1, ..., Tn) is equivalent to ComposeFunctors(Tn, ..., T1), but it's more |
| 112 | // efficient when all of the following must be evaluated: |
| 113 | // ReverseComposeFunctors<T1> |
| 114 | // ReverseComposeFunctors<T2, T1> |
| 115 | // ReverseComposeFunctors<T3, T2, T1> |
| 116 | // In that case, this implementation shares many more instantiations with previous invocations |
| 117 | struct ReverseComposeFunctors { |
| 118 | template <typename... Functors> |
| 119 | struct apply { |
| 120 | using type = ComponentFunctorIdentity; |
| 121 | }; |
| 122 | |
| 123 | template <typename Functor> |
| 124 | struct apply<Functor> { |
| 125 | using type = Functor; |
| 126 | }; |
| 127 | |
| 128 | template <typename Functor, typename... Functors> |
| 129 | struct apply<Functor, Functors...> { |
| 130 | using type = Compose2ComponentFunctors(ReverseComposeFunctors(Functors...), Functor); |
| 131 | }; |
| 132 | }; |
| 133 | |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 134 | struct EnsureProvidedType; |
| 135 | |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 136 | struct EnsureProvidedTypes; |
| 137 | |
Marco Poletti | 2edd866 | 2014-12-31 16:06:07 +0100 | [diff] [blame] | 138 | // Doesn't actually bind in ComponentStorage. The binding is added later (if needed) using ProcessInterfaceBinding. |
Marco Poletti | 2edd866 | 2014-12-31 16:06:07 +0100 | [diff] [blame] | 139 | struct AddDeferredInterfaceBinding { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 140 | template <typename Comp, typename AnnotatedI, typename AnnotatedC> |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 141 | struct apply { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 142 | using Comp1 = ConsComp(typename Comp::RsSuperset, |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 143 | typename Comp::Ps, |
Marco Poletti | 42c3b7c | 2016-05-22 09:32:36 +0100 | [diff] [blame] | 144 | #ifndef FRUIT_NO_LOOP_CHECK |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 145 | typename Comp::Deps, |
Marco Poletti | 42c3b7c | 2016-05-22 09:32:36 +0100 | [diff] [blame] | 146 | #endif |
Marco Poletti | ec5c520 | 2015-07-26 11:18:44 +0100 | [diff] [blame] | 147 | PushFront(typename Comp::InterfaceBindings, |
| 148 | Pair<AnnotatedI, AnnotatedC>), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 149 | typename Comp::DeferredBindingFunctors); |
| 150 | struct Op { |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 151 | // Note that we do NOT call AddProvidedType here. We'll only know the right required type |
| 152 | // when the binding will be used. |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 153 | using Result = Eval<Comp1>; |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 154 | void operator()(ComponentStorage&) {} |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 155 | }; |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 156 | using I = RemoveAnnotations(AnnotatedI); |
| 157 | using C = RemoveAnnotations(AnnotatedC); |
Marco Poletti | 6026b75 | 2016-02-21 14:30:31 +0000 | [diff] [blame] | 158 | using type = If(IsSame(I, C), |
| 159 | ConstructError(InterfaceBindingToSelfErrorTag, C), |
| 160 | If(Not(IsBaseOf(I, C)), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 161 | ConstructError(NotABaseClassOfErrorTag, I, C), |
Marco Poletti | 072fb36 | 2016-12-10 18:49:08 +0000 | [diff] [blame] | 162 | If(Not(IsSame(I, NormalizeType(I))), |
| 163 | ConstructError(NonClassTypeErrorTag, I, NormalizeType(I)), |
| 164 | If(Not(IsSame(C, NormalizeType(C))), |
| 165 | // We handle this case too, just to be on the safe side, but this should never happen. |
| 166 | ConstructError(NonClassTypeErrorTag, C, NormalizeType(C)), |
Marco Poletti | 417e045 | 2016-11-20 14:23:37 +0000 | [diff] [blame] | 167 | If(IsInSet(AnnotatedI, typename Comp::Ps), |
| 168 | ConstructError(TypeAlreadyBoundErrorTag, AnnotatedI), |
| 169 | If(MapContainsKey(typename Comp::InterfaceBindings, AnnotatedI), |
| 170 | ConstructError(TypeAlreadyBoundErrorTag, AnnotatedI), |
Marco Poletti | 072fb36 | 2016-12-10 18:49:08 +0000 | [diff] [blame] | 171 | Op)))))); |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 172 | }; |
| 173 | }; |
| 174 | |
Marco Poletti | 2edd866 | 2014-12-31 16:06:07 +0100 | [diff] [blame] | 175 | struct ProcessInterfaceBinding { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 176 | template <typename Comp, typename AnnotatedI, typename AnnotatedC> |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 177 | struct apply { |
Marco Poletti | dff7748 | 2016-03-26 11:20:10 +0000 | [diff] [blame] | 178 | using R = AddProvidedTypeIgnoringInterfaceBindings(Comp, AnnotatedI, Vector<AnnotatedC>); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 179 | struct Op { |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 180 | // This must be here (and not in AddDeferredInterfaceBinding) because the binding might be |
| 181 | // used to bind functors instead, so we might never need to add C to the requirements. |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 182 | using Result = Eval<R>; |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 183 | void operator()(ComponentStorage& storage) { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 184 | storage.addBinding(InjectorStorage::createBindingDataForBind< |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 185 | UnwrapType<AnnotatedI>, UnwrapType<AnnotatedC>>()); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 186 | }; |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 187 | }; |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 188 | using type = PropagateError(R, |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 189 | Op); |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 190 | }; |
| 191 | }; |
| 192 | |
Marco Poletti | 2edd866 | 2014-12-31 16:06:07 +0100 | [diff] [blame] | 193 | struct AddInterfaceMultibinding { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 194 | template <typename Comp, typename AnnotatedI, typename AnnotatedC> |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 195 | struct apply { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 196 | using I = RemoveAnnotations(AnnotatedI); |
| 197 | using C = RemoveAnnotations(AnnotatedC); |
| 198 | using R = AddRequirements(Comp, Vector<AnnotatedC>); |
| 199 | struct Op { |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 200 | using Result = Eval<R>; |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 201 | void operator()(ComponentStorage& storage) { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 202 | storage.addMultibinding(InjectorStorage::createMultibindingDataForBinding< |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 203 | UnwrapType<AnnotatedI>, UnwrapType<AnnotatedC>>()); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 204 | }; |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 205 | }; |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 206 | using type = If(Not(IsBaseOf(I, C)), |
| 207 | ConstructError(NotABaseClassOfErrorTag, I, C), |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 208 | Op); |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 209 | }; |
| 210 | }; |
| 211 | |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 212 | template <typename AnnotatedSignature, typename Lambda, typename OptionalAnnotatedI> |
Marco Poletti | cc97a16 | 2015-05-10 12:10:12 +0100 | [diff] [blame] | 213 | struct PostProcessRegisterProviderHelper; |
| 214 | |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 215 | template <typename AnnotatedSignature, typename Lambda, typename AnnotatedI> |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 216 | struct PostProcessRegisterProviderHelper; |
| 217 | |
| 218 | template <typename AnnotatedSignature, typename Lambda, typename AnnotatedI> |
| 219 | struct PostProcessRegisterProviderHelper<AnnotatedSignature, Lambda, Type<AnnotatedI>> { |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 220 | inline void operator()(ComponentStorage& component) { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 221 | component.addBinding(InjectorStorage::createBindingDataForProvider< |
| 222 | AnnotatedSignature, Lambda>()); |
| 223 | component.addCompressedBinding(InjectorStorage::createBindingDataForCompressedProvider< |
| 224 | AnnotatedSignature, Lambda, AnnotatedI>()); |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 225 | } |
| 226 | }; |
| 227 | |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 228 | template <typename AnnotatedSignature, typename Lambda> |
| 229 | struct PostProcessRegisterProviderHelper<AnnotatedSignature, Lambda, None> { |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 230 | inline void operator()(ComponentStorage& component) { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 231 | component.addBinding(InjectorStorage::createBindingDataForProvider< |
| 232 | AnnotatedSignature, Lambda>()); |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 233 | } |
| 234 | }; |
| 235 | |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 236 | // T can't be any injectable type, it must match the return type of the provider in one of |
| 237 | // the registerProvider() overloads in ComponentStorage. |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 238 | struct PostProcessRegisterProvider { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 239 | template <typename Comp, typename AnnotatedSignature, typename Lambda> |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 240 | struct apply { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 241 | using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature)); |
Marco Poletti | 1e44d55 | 2017-05-20 14:10:38 +0100 | [diff] [blame^] | 242 | using OptionalAnnotatedI = FindValueInMap(typename Comp::InterfaceBindings, AnnotatedC); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 243 | struct Op { |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 244 | using Result = Comp; |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 245 | void operator()(ComponentStorage& storage) { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 246 | PostProcessRegisterProviderHelper< |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 247 | UnwrapType<AnnotatedSignature>, UnwrapType<Lambda>, Eval<OptionalAnnotatedI>>()(storage); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 248 | } |
| 249 | }; |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 250 | using type = Op; |
Marco Poletti | d8943a8 | 2015-01-01 15:57:16 +0100 | [diff] [blame] | 251 | }; |
| 252 | }; |
| 253 | |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 254 | struct PreProcessRegisterProvider { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 255 | template <typename Comp, typename AnnotatedSignature, typename Lambda> |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 256 | struct apply { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 257 | using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature); |
| 258 | using SignatureFromLambda = FunctionSignature(Lambda); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 259 | |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 260 | using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature)); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 261 | using AnnotatedCDeps = ExpandProvidersInParams(NormalizeTypeVector(SignatureArgs(AnnotatedSignature))); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 262 | using R = AddProvidedType(Comp, AnnotatedC, AnnotatedCDeps); |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 263 | using type = If(Not(IsSame(Signature, SignatureFromLambda)), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 264 | ConstructError(AnnotatedSignatureDifferentFromLambdaSignatureErrorTag, Signature, SignatureFromLambda), |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 265 | ComponentFunctorIdentity(R)); |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 266 | }; |
| 267 | }; |
| 268 | |
| 269 | // The registration is actually deferred until the PartialComponent is converted to a component. |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 270 | struct DeferredRegisterProviderWithAnnotations { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 271 | template <typename Comp, typename AnnotatedSignature, typename Lambda> |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 272 | struct apply { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 273 | using Comp1 = AddDeferredBinding(Comp, |
| 274 | ComponentFunctor(PostProcessRegisterProvider, AnnotatedSignature, Lambda)); |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 275 | using type = PreProcessRegisterProvider(Comp1, AnnotatedSignature, Lambda); |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 276 | }; |
| 277 | }; |
| 278 | |
Marco Poletti | d8943a8 | 2015-01-01 15:57:16 +0100 | [diff] [blame] | 279 | // The registration is actually deferred until the PartialComponent is converted to a component. |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 280 | struct DeferredRegisterProvider { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 281 | template <typename Comp, typename Lambda> |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 282 | struct apply { |
Marco Poletti | ebe1225 | 2016-03-26 11:41:40 +0000 | [diff] [blame] | 283 | using type = DeferredRegisterProviderWithAnnotations(Comp, FunctionSignature(Lambda), Lambda); |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 284 | }; |
| 285 | }; |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 286 | |
| 287 | // T can't be any injectable type, it must match the return type of the provider in one of |
| 288 | // the registerMultibindingProvider() overloads in ComponentStorage. |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 289 | struct RegisterMultibindingProviderWithAnnotations { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 290 | template <typename Comp, typename AnnotatedSignature, typename Lambda> |
Marco Poletti | d8943a8 | 2015-01-01 15:57:16 +0100 | [diff] [blame] | 291 | struct apply { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 292 | using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature); |
| 293 | using SignatureFromLambda = FunctionSignature(Lambda); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 294 | |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 295 | using AnnotatedArgs = SignatureArgs(AnnotatedSignature); |
| 296 | using AnnotatedArgVector = ExpandProvidersInParams(NormalizeTypeVector(AnnotatedArgs)); |
| 297 | using R = AddRequirements(Comp, AnnotatedArgVector); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 298 | struct Op { |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 299 | using Result = Eval<R>; |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 300 | void operator()(ComponentStorage& storage) { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 301 | auto multibindingData = InjectorStorage::createMultibindingDataForProvider< |
| 302 | UnwrapType<AnnotatedSignature>, UnwrapType<Lambda>>(); |
| 303 | storage.addMultibinding(multibindingData); |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 304 | } |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 305 | }; |
Marco Poletti | 3c54483 | 2015-12-01 22:52:21 +0100 | [diff] [blame] | 306 | using type = If(Not(IsValidSignature(AnnotatedSignature)), |
| 307 | ConstructError(NotASignatureErrorTag, AnnotatedSignature), |
| 308 | If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))), |
| 309 | ConstructError(CannotConstructAbstractClassErrorTag, RemoveAnnotations(SignatureType(AnnotatedSignature))), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 310 | If(Not(IsSame(Signature, SignatureFromLambda)), |
| 311 | ConstructError(AnnotatedSignatureDifferentFromLambdaSignatureErrorTag, Signature, SignatureFromLambda), |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 312 | PropagateError(R, |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 313 | Op)))); |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 314 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 315 | }; |
| 316 | |
| 317 | // T can't be any injectable type, it must match the return type of the provider in one of |
| 318 | // the registerMultibindingProvider() overloads in ComponentStorage. |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 319 | struct RegisterMultibindingProvider { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 320 | template <typename Comp, typename Lambda> |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 321 | struct apply { |
Marco Poletti | ebe1225 | 2016-03-26 11:41:40 +0000 | [diff] [blame] | 322 | using type = RegisterMultibindingProviderWithAnnotations(Comp, FunctionSignature(Lambda), Lambda); |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 323 | }; |
| 324 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 325 | |
| 326 | // Non-assisted case. |
Marco Poletti | 905dc09 | 2017-03-12 15:54:31 +0000 | [diff] [blame] | 327 | template <int numAssistedBefore, int numNonAssistedBefore, typename Arg> |
Marco Poletti | 9754d5a | 2014-11-24 19:46:28 +0000 | [diff] [blame] | 328 | struct GetAssistedArg { |
Marco Poletti | 905dc09 | 2017-03-12 15:54:31 +0000 | [diff] [blame] | 329 | template <typename InjectedArgsTuple, typename UserProvidedArgsTuple> |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 330 | inline Arg operator()(InjectedArgsTuple& injected_args, UserProvidedArgsTuple&) { |
| 331 | return std::get<numNonAssistedBefore>(injected_args); |
| 332 | } |
| 333 | }; |
| 334 | |
| 335 | // Assisted case. |
Marco Poletti | 905dc09 | 2017-03-12 15:54:31 +0000 | [diff] [blame] | 336 | template <int numAssistedBefore, int numNonAssistedBefore, typename Arg> |
| 337 | struct GetAssistedArg<numAssistedBefore, numNonAssistedBefore, Assisted<Arg>> { |
| 338 | template <typename InjectedArgsTuple, typename UserProvidedArgsTuple> |
| 339 | inline Arg operator()(InjectedArgsTuple&, UserProvidedArgsTuple& user_provided_args) { |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 340 | return std::get<numAssistedBefore>(user_provided_args); |
| 341 | } |
| 342 | }; |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 343 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 344 | struct RegisterFactoryHelper { |
| 345 | |
| 346 | template <typename Comp, |
| 347 | typename DecoratedSignature, |
| 348 | typename Lambda, |
| 349 | // std::function<InjectedSignature> is the injected type (possibly with an Annotation<> wrapping it) |
| 350 | typename InjectedSignature, |
| 351 | typename RequiredLambdaSignature, |
| 352 | typename InjectedAnnotatedArgs, |
| 353 | // The types that are injected, unwrapped from any Annotation<>. |
| 354 | typename InjectedArgs, |
| 355 | typename IndexSequence> |
| 356 | struct apply; |
| 357 | |
| 358 | template <typename Comp, typename DecoratedSignature, typename Lambda, typename NakedC, |
| 359 | typename... NakedUserProvidedArgs, typename... NakedAllArgs, typename... InjectedAnnotatedArgs, |
Marco Poletti | 905dc09 | 2017-03-12 15:54:31 +0000 | [diff] [blame] | 360 | typename... NakedInjectedArgs, typename... Indexes> |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 361 | struct apply<Comp, DecoratedSignature, Lambda, Type<NakedC(NakedUserProvidedArgs...)>, |
| 362 | Type<NakedC(NakedAllArgs...)>, Vector<InjectedAnnotatedArgs...>, |
Marco Poletti | 905dc09 | 2017-03-12 15:54:31 +0000 | [diff] [blame] | 363 | Vector<Type<NakedInjectedArgs>...>, Vector<Indexes...>> { |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 364 | // Here we call "decorated" the types that might be wrapped in Annotated<> or Assisted<>, |
| 365 | // while we call "annotated" the ones that might only be wrapped in Annotated<> (but not Assisted<>). |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 366 | using AnnotatedT = SignatureType(DecoratedSignature); |
| 367 | using T = RemoveAnnotations(AnnotatedT); |
| 368 | using DecoratedArgs = SignatureArgs(DecoratedSignature); |
| 369 | using NakedInjectedSignature = NakedC(NakedUserProvidedArgs...); |
| 370 | using NakedRequiredSignature = NakedC(NakedAllArgs...); |
| 371 | using NakedFunctor = std::function<NakedInjectedSignature>; |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 372 | // This is usually the same as Functor, but this might be annotated. |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 373 | using AnnotatedFunctor = CopyAnnotation(AnnotatedT, Type<NakedFunctor>); |
| 374 | using FunctorDeps = NormalizeTypeVector(Vector<InjectedAnnotatedArgs...>); |
| 375 | using R = AddProvidedType(Comp, AnnotatedFunctor, FunctorDeps); |
| 376 | struct Op { |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 377 | using Result = Eval<R>; |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 378 | void operator()(ComponentStorage& storage) { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 379 | auto function_provider = [](NakedInjectedArgs... args) { |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 380 | // TODO: Using auto and make_tuple here results in a GCC segfault with GCC 4.8.1. |
| 381 | // Check this on later versions and consider filing a bug. |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 382 | std::tuple<NakedInjectedArgs...> injected_args(args...); |
| 383 | auto object_provider = [injected_args](NakedUserProvidedArgs... params) mutable { |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 384 | auto user_provided_args = std::tie(params...); |
Marco Poletti | 905dc09 | 2017-03-12 15:54:31 +0000 | [diff] [blame] | 385 | // These are unused if they are 0-arg tuples. Silence the unused-variable warnings anyway. |
| 386 | (void) injected_args; |
| 387 | (void) user_provided_args; |
| 388 | |
| 389 | return LambdaInvoker::invoke<UnwrapType<Lambda>, NakedAllArgs...>( |
| 390 | GetAssistedArg< |
| 391 | Eval<NumAssistedBefore(Indexes, DecoratedArgs)>::value, |
| 392 | Indexes::value - Eval<NumAssistedBefore(Indexes, DecoratedArgs)>::value, |
| 393 | // Note that the Assisted<> wrapper (if any) remains, we just remove any wrapping Annotated<>. |
| 394 | UnwrapType<Eval<RemoveAnnotations(GetNthType(Indexes, DecoratedArgs))>> |
| 395 | >()(injected_args, user_provided_args)...); |
| 396 | }; |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 397 | return NakedFunctor(object_provider); |
Marco Poletti | cc97a16 | 2015-05-10 12:10:12 +0100 | [diff] [blame] | 398 | }; |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 399 | storage.addBinding(InjectorStorage::createBindingDataForProvider< |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 400 | UnwrapType<Eval<ConsSignatureWithVector(AnnotatedFunctor, Vector<InjectedAnnotatedArgs...>)>>, |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 401 | decltype(function_provider)>()); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 402 | } |
| 403 | }; |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 404 | // The first two IsValidSignature checks are a bit of a hack, they are needed to make the F2/RealF2 split |
Marco Poletti | f41d236 | 2015-12-07 17:03:51 +0000 | [diff] [blame] | 405 | // work in the caller (we need to allow Lambda to be a function type). |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 406 | using type = If(Not(Or(IsEmpty(Lambda), IsValidSignature(Lambda))), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 407 | ConstructError(LambdaWithCapturesErrorTag, Lambda), |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 408 | If(Not(Or(IsTriviallyCopyable(Lambda), IsValidSignature(Lambda))), |
Marco Poletti | f41d236 | 2015-12-07 17:03:51 +0000 | [diff] [blame] | 409 | ConstructError(NonTriviallyCopyableLambdaErrorTag, Lambda), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 410 | If(Not(IsSame(Type<NakedRequiredSignature>, FunctionSignature(Lambda))), |
| 411 | ConstructError(FunctorSignatureDoesNotMatchErrorTag, Type<NakedRequiredSignature>, FunctionSignature(Lambda)), |
| 412 | If(IsPointer(T), |
| 413 | ConstructError(FactoryReturningPointerErrorTag, DecoratedSignature), |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 414 | PropagateError(R, |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 415 | Op))))); |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 416 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 417 | }; |
| 418 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 419 | struct RegisterFactory { |
| 420 | template <typename Comp, typename DecoratedSignature, typename Lambda> |
| 421 | struct apply { |
Marco Poletti | 3c54483 | 2015-12-01 22:52:21 +0100 | [diff] [blame] | 422 | using type = If(Not(IsValidSignature(DecoratedSignature)), |
| 423 | ConstructError(NotASignatureErrorTag, DecoratedSignature), |
| 424 | If(IsAbstract(RemoveAnnotations(SignatureType(DecoratedSignature))), |
| 425 | // We error out early in this case. Calling RegisterFactoryHelper would also produce an error, but it'd be |
| 426 | // much less user-friendly. |
| 427 | ConstructError(CannotConstructAbstractClassErrorTag, RemoveAnnotations(SignatureType(DecoratedSignature))), |
| 428 | RegisterFactoryHelper(Comp, |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 429 | DecoratedSignature, |
| 430 | Lambda, |
| 431 | InjectedSignatureForAssistedFactory(DecoratedSignature), |
| 432 | RequiredLambdaSignatureForAssistedFactory(DecoratedSignature), |
| 433 | RemoveAssisted(SignatureArgs(DecoratedSignature)), |
| 434 | RemoveAnnotationsFromVector(RemoveAssisted(SignatureArgs(DecoratedSignature))), |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 435 | GenerateIntSequence( |
Marco Poletti | 3c54483 | 2015-12-01 22:52:21 +0100 | [diff] [blame] | 436 | VectorSize(RequiredLambdaArgsForAssistedFactory(DecoratedSignature)))))); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 437 | }; |
| 438 | }; |
| 439 | |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 440 | struct PostProcessRegisterConstructor; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 441 | |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 442 | template <typename AnnotatedSignature, typename OptionalAnnotatedI> |
Marco Poletti | cc97a16 | 2015-05-10 12:10:12 +0100 | [diff] [blame] | 443 | struct PostProcessRegisterConstructorHelper; |
| 444 | |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 445 | template <typename AnnotatedSignature, typename AnnotatedI> |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 446 | struct PostProcessRegisterConstructorHelper; |
| 447 | |
| 448 | template <typename AnnotatedSignature, typename AnnotatedI> |
| 449 | struct PostProcessRegisterConstructorHelper<AnnotatedSignature, Type<AnnotatedI>> { |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 450 | inline void operator()(ComponentStorage& component) { |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 451 | component.addBinding(InjectorStorage::createBindingDataForConstructor<AnnotatedSignature>()); |
| 452 | component.addCompressedBinding(InjectorStorage::createBindingDataForCompressedConstructor<AnnotatedSignature, AnnotatedI>()); |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 453 | } |
| 454 | }; |
| 455 | |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 456 | template <typename AnnotatedSignature> |
| 457 | struct PostProcessRegisterConstructorHelper<AnnotatedSignature, None> { |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 458 | inline void operator()(ComponentStorage& component) { |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 459 | component.addBinding(InjectorStorage::createBindingDataForConstructor<AnnotatedSignature>()); |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 460 | } |
| 461 | }; |
| 462 | |
Marco Poletti | 31f638a | 2015-05-10 21:21:25 +0100 | [diff] [blame] | 463 | struct PostProcessRegisterConstructor { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 464 | template <typename Comp, typename AnnotatedSignature> |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 465 | struct apply { |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 466 | struct type { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 467 | using AnnotatedC = NormalizeType(SignatureType(AnnotatedSignature)); |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 468 | using Result = Comp; |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 469 | void operator()(ComponentStorage& storage) { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 470 | PostProcessRegisterConstructorHelper< |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 471 | UnwrapType<AnnotatedSignature>, |
Marco Poletti | 1e44d55 | 2017-05-20 14:10:38 +0100 | [diff] [blame^] | 472 | Eval<FindValueInMap(typename Comp::InterfaceBindings, AnnotatedC)> |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 473 | >()(storage); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 474 | } |
| 475 | }; |
Marco Poletti | d8943a8 | 2015-01-01 15:57:16 +0100 | [diff] [blame] | 476 | }; |
| 477 | }; |
| 478 | |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 479 | struct PreProcessRegisterConstructor { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 480 | template <typename Comp, typename AnnotatedSignature> |
Marco Poletti | d8943a8 | 2015-01-01 15:57:16 +0100 | [diff] [blame] | 481 | struct apply { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 482 | using Signature = RemoveAnnotationsFromSignature(AnnotatedSignature); |
| 483 | using C = SignatureType(Signature); |
| 484 | using Args = SignatureArgs(Signature); |
| 485 | using AnnotatedT = SignatureType(AnnotatedSignature); |
| 486 | using AnnotatedArgs = SignatureArgs(AnnotatedSignature); |
| 487 | using AnnotatedC = NormalizeType(AnnotatedT); |
| 488 | using CDeps = ExpandProvidersInParams(NormalizeTypeVector(AnnotatedArgs)); |
| 489 | using R = AddProvidedType(Comp, AnnotatedC, CDeps); |
Marco Poletti | 3c54483 | 2015-12-01 22:52:21 +0100 | [diff] [blame] | 490 | using type = If(Not(IsValidSignature(AnnotatedSignature)), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 491 | ConstructError(NotASignatureErrorTag, AnnotatedSignature), |
Marco Poletti | 3c54483 | 2015-12-01 22:52:21 +0100 | [diff] [blame] | 492 | If(IsAbstract(RemoveAnnotations(SignatureType(AnnotatedSignature))), |
| 493 | ConstructError(CannotConstructAbstractClassErrorTag, RemoveAnnotations(SignatureType(AnnotatedSignature))), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 494 | If(Not(IsConstructibleWithVector(C, Args)), |
| 495 | ConstructError(NoConstructorMatchingInjectSignatureErrorTag, C, Signature), |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 496 | PropagateError(R, |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 497 | ComponentFunctorIdentity(R))))); |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 498 | }; |
| 499 | }; |
| 500 | |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 501 | struct DeferredRegisterConstructor { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 502 | template <typename Comp, typename AnnotatedSignature> |
Marco Poletti | e9c143b | 2015-03-08 16:46:50 +0000 | [diff] [blame] | 503 | struct apply { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 504 | using Comp1 = AddDeferredBinding(Comp, |
| 505 | ComponentFunctor(PostProcessRegisterConstructor, AnnotatedSignature)); |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 506 | using type = PreProcessRegisterConstructor(Comp1, AnnotatedSignature); |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 507 | }; |
| 508 | }; |
| 509 | |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 510 | struct RegisterInstance { |
Marco Poletti | 0acba69 | 2016-12-10 17:44:38 +0000 | [diff] [blame] | 511 | template <typename Comp, typename AnnotatedC, typename C> |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 512 | struct apply { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 513 | using R = AddProvidedType(Comp, AnnotatedC, Vector<>); |
| 514 | struct Op { |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 515 | using Result = Eval<R>; |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 516 | void operator()(ComponentStorage&) {} |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 517 | }; |
Marco Poletti | 0acba69 | 2016-12-10 17:44:38 +0000 | [diff] [blame] | 518 | using type = If(Not(IsSame(C, NormalizeType(C))), |
| 519 | ConstructError(NonClassTypeErrorTag, C, NormalizeType(C)), |
| 520 | If(Not(IsSame(RemoveAnnotations(AnnotatedC), NormalizeType(RemoveAnnotations(AnnotatedC)))), |
| 521 | ConstructError(NonClassTypeErrorTag, RemoveAnnotations(AnnotatedC), NormalizeType(RemoveAnnotations(C))), |
| 522 | // The IsSame check is not redundant because IsBaseOf returns false for non-class types (e.g. int). |
| 523 | If(Not(Or(IsSame(RemoveAnnotations(AnnotatedC), C), |
| 524 | IsBaseOf(RemoveAnnotations(AnnotatedC), C))), |
| 525 | ConstructError(TypeMismatchInBindInstanceErrorTag, RemoveAnnotations(AnnotatedC), C), |
| 526 | PropagateError(R, |
| 527 | Op)))); |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 528 | }; |
| 529 | }; |
| 530 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 531 | struct RegisterConstructorAsValueFactory { |
| 532 | template<typename Comp, |
| 533 | typename DecoratedSignature, |
| 534 | typename RequiredSignature = |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 535 | Eval<RequiredLambdaSignatureForAssistedFactory(DecoratedSignature)>> |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 536 | struct apply; |
| 537 | |
| 538 | template <typename Comp, typename DecoratedSignature, typename NakedT, typename... NakedArgs> |
| 539 | struct apply<Comp, DecoratedSignature, Type<NakedT(NakedArgs...)>> { |
| 540 | using RequiredSignature = Type<NakedT(NakedArgs...)>; |
| 541 | using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature); |
| 542 | struct Op { |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 543 | using Result = Eval<GetResult(Op1)>; |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 544 | void operator()(ComponentStorage& storage) { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 545 | auto provider = [](NakedArgs... args) { |
| 546 | return NakedT(std::forward<NakedArgs>(args)...); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 547 | }; |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 548 | using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>); |
| 549 | FruitStaticAssert(IsSame(GetResult(Op1), |
| 550 | GetResult(RealOp))); |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 551 | Eval<RealOp>()(storage); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 552 | } |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 553 | }; |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 554 | using type = PropagateError(Op1, |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 555 | Op); |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 556 | }; |
| 557 | }; |
| 558 | |
Marco Poletti | 0e7e515 | 2016-05-14 09:20:05 +0100 | [diff] [blame] | 559 | |
| 560 | struct RegisterConstructorAsUniquePtrFactory { |
| 561 | template<typename Comp, |
| 562 | typename DecoratedSignature, |
| 563 | typename RequiredSignature = |
| 564 | Eval<RequiredLambdaSignatureForAssistedFactory(DecoratedSignature)>> |
| 565 | struct apply; |
| 566 | |
| 567 | template <typename Comp, typename DecoratedSignature, typename NakedT, typename... NakedArgs> |
| 568 | struct apply<Comp, DecoratedSignature, Type<std::unique_ptr<NakedT>(NakedArgs...)>> { |
| 569 | using RequiredSignature = Type<std::unique_ptr<NakedT>(NakedArgs...)>; |
| 570 | using Op1 = RegisterFactory(Comp, DecoratedSignature, RequiredSignature); |
| 571 | struct Op { |
| 572 | using Result = Eval<GetResult(Op1)>; |
| 573 | void operator()(ComponentStorage& storage) { |
| 574 | auto provider = [](NakedArgs... args) { |
| 575 | return std::unique_ptr<NakedT>(new NakedT(std::forward<NakedArgs>(args)...)); |
| 576 | }; |
| 577 | using RealOp = RegisterFactory(Comp, DecoratedSignature, Type<decltype(provider)>); |
| 578 | FruitStaticAssert(IsSame(GetResult(Op1), |
| 579 | GetResult(RealOp))); |
| 580 | Eval<RealOp>()(storage); |
| 581 | }; |
| 582 | }; |
| 583 | |
| 584 | using type = PropagateError(Op1, |
| 585 | Op); |
| 586 | }; |
| 587 | }; |
| 588 | |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 589 | struct InstallComponent { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 590 | template <typename Comp, typename OtherComp> |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 591 | struct apply { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 592 | using new_RsSuperset = SetUnion(typename OtherComp::RsSuperset, |
| 593 | typename Comp::RsSuperset); |
Marco Poletti | ec5c520 | 2015-07-26 11:18:44 +0100 | [diff] [blame] | 594 | using new_Ps = SetUncheckedUnion(typename OtherComp::Ps, |
| 595 | typename Comp::Ps); |
Marco Poletti | 42c3b7c | 2016-05-22 09:32:36 +0100 | [diff] [blame] | 596 | #ifndef FRUIT_NO_LOOP_CHECK |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 597 | using new_Deps = ConcatVectors(typename OtherComp::Deps, |
| 598 | typename Comp::Deps); |
Marco Poletti | 42c3b7c | 2016-05-22 09:32:36 +0100 | [diff] [blame] | 599 | #endif |
Marco Poletti | cd6625f | 2016-03-26 11:31:08 +0000 | [diff] [blame] | 600 | FruitStaticAssert(IsSame(typename OtherComp::InterfaceBindings, Vector<>)); |
| 601 | using new_InterfaceBindings = typename Comp::InterfaceBindings; |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 602 | |
| 603 | FruitStaticAssert(IsSame(typename OtherComp::DeferredBindingFunctors, EmptyList)); |
| 604 | using new_DeferredBindingFunctors = typename Comp::DeferredBindingFunctors; |
| 605 | |
Marco Poletti | 42c3b7c | 2016-05-22 09:32:36 +0100 | [diff] [blame] | 606 | using R = ConsComp(new_RsSuperset, new_Ps, |
| 607 | #ifndef FRUIT_NO_LOOP_CHECK |
| 608 | new_Deps, |
| 609 | #endif |
| 610 | new_InterfaceBindings, new_DeferredBindingFunctors); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 611 | struct Op { |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 612 | using Result = Eval<R>; |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 613 | void operator()(ComponentStorage&) {} |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 614 | }; |
Marco Poletti | 417e045 | 2016-11-20 14:23:37 +0000 | [diff] [blame] | 615 | using InterfacePs = VectorToSetUnchecked(GetMapKeys(typename Comp::InterfaceBindings)); |
| 616 | using AllPs = SetUncheckedUnion(InterfacePs, typename Comp::Ps); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 617 | using DuplicateTypes = SetIntersection(typename OtherComp::Ps, |
Marco Poletti | 417e045 | 2016-11-20 14:23:37 +0000 | [diff] [blame] | 618 | AllPs); |
| 619 | using type = If(Not(IsDisjoint(typename OtherComp::Ps, AllPs)), |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 620 | ConstructErrorWithArgVector(DuplicateTypesInComponentErrorTag, |
| 621 | SetToVector(DuplicateTypes)), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 622 | Op); |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 623 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 624 | }; |
| 625 | |
Marco Poletti | a19fd1e | 2015-03-07 18:50:37 +0000 | [diff] [blame] | 626 | struct InstallComponentHelper { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 627 | template <typename Comp, typename... OtherCompParams> |
Marco Poletti | a19fd1e | 2015-03-07 18:50:37 +0000 | [diff] [blame] | 628 | struct apply { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 629 | using OtherComp = ConstructComponentImpl(OtherCompParams...); |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 630 | using type = InstallComponent(Comp, OtherComp); |
Marco Poletti | a19fd1e | 2015-03-07 18:50:37 +0000 | [diff] [blame] | 631 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 632 | }; |
| 633 | |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 634 | struct ConvertComponent { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 635 | template <typename SourceComp, typename DestComp> |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 636 | struct apply { |
| 637 | // We need to register: |
| 638 | // * All the types provided by the new component |
| 639 | // * All the types required by the old component |
| 640 | // except: |
| 641 | // * The ones already provided by the old component. |
| 642 | // * The ones required by the new one. |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 643 | using SourcePs = typename SourceComp::Ps; |
| 644 | using DestPs = typename DestComp::Ps; |
| 645 | using SourceRs = SetDifference(typename SourceComp::RsSuperset, typename SourceComp::Ps); |
| 646 | using DestRs = SetDifference(typename DestComp::RsSuperset, typename DestComp::Ps); |
| 647 | using ToRegister = SetDifference(SetUnion(DestPs, SourceRs), |
| 648 | SetUnion(DestRs, SourcePs)); |
| 649 | using type = EnsureProvidedTypes(SourceComp, DestRs, SetToVector(ToRegister)); |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 650 | |
| 651 | // Not needed, just double-checking. |
| 652 | // Uses FruitStaticAssert instead of FruitDelegateCheck so that it's checked only in debug mode. |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 653 | #ifdef FRUIT_EXTRA_DEBUG |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 654 | FruitDelegateCheck(CheckComponentEntails(GetResult(type), DestComp)); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 655 | #endif // FRUIT_EXTRA_DEBUG |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 656 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 657 | }; |
| 658 | |
Marco Poletti | d8943a8 | 2015-01-01 15:57:16 +0100 | [diff] [blame] | 659 | struct ProcessDeferredBindings { |
| 660 | template <typename Comp> |
| 661 | struct apply; |
| 662 | |
Marco Poletti | 42c3b7c | 2016-05-22 09:32:36 +0100 | [diff] [blame] | 663 | template <typename RsSupersetParam, typename PsParam, |
| 664 | #ifndef FRUIT_NO_LOOP_CHECK |
| 665 | typename DepsParam, |
| 666 | #endif |
| 667 | typename InterfaceBindingsParam, typename DeferredBindingFunctors> |
| 668 | struct apply<Comp<RsSupersetParam, PsParam, |
| 669 | #ifndef FRUIT_NO_LOOP_CHECK |
| 670 | DepsParam, |
| 671 | #endif |
| 672 | InterfaceBindingsParam, DeferredBindingFunctors>> { |
Marco Poletti | d8943a8 | 2015-01-01 15:57:16 +0100 | [diff] [blame] | 673 | // Comp1 is the same as Comp, but without the DeferredBindingFunctors. |
Marco Poletti | 42c3b7c | 2016-05-22 09:32:36 +0100 | [diff] [blame] | 674 | using Comp1 = ConsComp(RsSupersetParam, PsParam, |
| 675 | #ifndef FRUIT_NO_LOOP_CHECK |
| 676 | DepsParam, |
| 677 | #endif |
| 678 | InterfaceBindingsParam, EmptyList); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 679 | using type = Call(FoldList(DeferredBindingFunctors, Compose2ComponentFunctors, ComponentFunctorIdentity), |
| 680 | Comp1); |
Marco Poletti | d8943a8 | 2015-01-01 15:57:16 +0100 | [diff] [blame] | 681 | }; |
| 682 | }; |
| 683 | |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 684 | template <typename AnnotatedCFunctor, typename AnnotatedCUniquePtrFunctor> |
| 685 | struct AutoRegisterFactoryHelperErrorHandler { |
| 686 | template <typename E> |
| 687 | struct apply { |
| 688 | using type = E; |
| 689 | }; |
Marco Poletti | 66918a4 | 2017-01-01 11:17:57 +0100 | [diff] [blame] | 690 | |
| 691 | template <typename T> |
| 692 | struct apply<Error<NoBindingFoundErrorTag, T>> { |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 693 | using type = If(IsSame(Type<T>, AnnotatedCFunctor), |
Marco Poletti | 66918a4 | 2017-01-01 11:17:57 +0100 | [diff] [blame] | 694 | ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor), |
| 695 | ConstructError(NoBindingFoundErrorTag, Type<T>)); |
| 696 | }; |
| 697 | |
| 698 | template <typename T1, typename T2> |
| 699 | struct apply<Error<NoBindingFoundForAbstractClassErrorTag, T1, T2>> { |
| 700 | using type = If(IsSame(Type<T1>, AnnotatedCFunctor), |
| 701 | ConstructNoBindingFoundError(AnnotatedCUniquePtrFunctor), |
| 702 | ConstructError(NoBindingFoundForAbstractClassErrorTag, Type<T1>, Type<T2>)); |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 703 | }; |
| 704 | }; |
| 705 | |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 706 | struct AutoRegisterFactoryHelper { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 707 | |
| 708 | // General case, no way to bind it. |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 709 | template <typename Comp, typename TargetRequirements, typename InterfaceBinding, |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 710 | typename has_inject_annotation, typename is_abstract, typename C, |
| 711 | typename AnnotatedSignature, typename... Args> |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 712 | struct apply { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 713 | using AnnotatedC = SignatureType(AnnotatedSignature); |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 714 | using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature)); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 715 | using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor); |
Marco Poletti | 3c54483 | 2015-12-01 22:52:21 +0100 | [diff] [blame] | 716 | using type = If(IsAbstract(C), |
Marco Poletti | 66918a4 | 2017-01-01 11:17:57 +0100 | [diff] [blame] | 717 | ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, C), |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 718 | ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor)); |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 719 | }; |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 720 | |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 721 | // No way to bind it (we need this specialization too to ensure that the specialization below |
Marco Poletti | 0954754 | 2015-07-25 12:13:24 +0100 | [diff] [blame] | 722 | // is not chosen for AnnotatedC=None). |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 723 | template <typename Comp, typename TargetRequirements, typename unused1, typename unused2, |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 724 | typename NakedI, typename AnnotatedSignature, typename... Args> |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 725 | struct apply<Comp, TargetRequirements, None, unused1, unused2, Type<std::unique_ptr<NakedI>>, |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 726 | AnnotatedSignature, Args...> { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 727 | using AnnotatedC = SignatureType(AnnotatedSignature); |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 728 | using CFunctor = ConsStdFunction(RemoveAnnotationsFromSignature(AnnotatedSignature)); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 729 | using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor); |
Marco Poletti | 3c54483 | 2015-12-01 22:52:21 +0100 | [diff] [blame] | 730 | using type = If(IsAbstract(Type<NakedI>), |
Marco Poletti | 66918a4 | 2017-01-01 11:17:57 +0100 | [diff] [blame] | 731 | ConstructError(NoBindingFoundForAbstractClassErrorTag, AnnotatedCFunctor, Type<NakedI>), |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 732 | ConstructError(NoBindingFoundErrorTag, AnnotatedCFunctor)); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 733 | }; |
| 734 | |
| 735 | // AnnotatedI has an interface binding, use it and look for a factory that returns the type that AnnotatedI is bound to. |
| 736 | template <typename Comp, typename TargetRequirements, typename AnnotatedC, typename unused1, typename unused2, |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 737 | typename NakedI, typename AnnotatedSignature, typename... Args> |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 738 | struct apply<Comp, TargetRequirements, AnnotatedC, unused1, unused2, Type<std::unique_ptr<NakedI>>, |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 739 | AnnotatedSignature, Args...> { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 740 | using I = Type<NakedI>; |
| 741 | using AnnotatedI = CopyAnnotation(SignatureType(AnnotatedSignature), I); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 742 | using C = RemoveAnnotations(AnnotatedC); |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 743 | using IFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(I), Args...)); |
| 744 | using CFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...)); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 745 | using AnnotatedIFunctor = CopyAnnotation(AnnotatedI, IFunctor); |
| 746 | using AnnotatedCFunctor = CopyAnnotation(AnnotatedC, CFunctor); |
| 747 | |
| 748 | using ProvidedSignature = ConsSignature(AnnotatedIFunctor, CopyAnnotation(AnnotatedC, ConsReference(CFunctor))); |
| 749 | using LambdaSignature = ConsSignature(IFunctor, ConsReference(CFunctor)); |
| 750 | |
| 751 | using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, AnnotatedCFunctor); |
| 752 | using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature); |
| 753 | using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 754 | using R = Call(ComposeFunctors(F1, F2, F3), Comp); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 755 | struct Op { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 756 | using Result = Eval<GetResult(R)>; |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 757 | void operator()(ComponentStorage& storage) { |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 758 | using NakedC = UnwrapType<Eval<C>>; |
| 759 | auto provider = [](UnwrapType<Eval<CFunctor>>& fun) { |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 760 | return UnwrapType<Eval<IFunctor>>([=](UnwrapType<Args>... args) { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 761 | NakedC* c = fun(args...).release(); |
| 762 | NakedI* i = static_cast<NakedI*>(c); |
| 763 | return std::unique_ptr<NakedI>(i); |
| 764 | }); |
| 765 | }; |
| 766 | using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); |
| 767 | using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); |
| 768 | using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 769 | FruitStaticAssert(IsSame(GetResult(RealOp), GetResult(R))); |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 770 | Eval<RealOp>()(storage); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 771 | } |
| 772 | }; |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 773 | using type = PropagateError(R, |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 774 | Op); |
| 775 | }; |
| 776 | |
| 777 | // C doesn't have an interface binding as interface, nor an INJECT annotation, and is not an abstract class. |
| 778 | // Bind std::function<unique_ptr<C>(Args...)> to std::function<C(Args...)> (possibly with annotations). |
| 779 | template <typename Comp, typename TargetRequirements, typename NakedC, typename AnnotatedSignature, |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 780 | typename... Args> |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 781 | struct apply<Comp, TargetRequirements, None, Bool<false>, Bool<false>, |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 782 | Type<std::unique_ptr<NakedC>>, AnnotatedSignature, Args...> { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 783 | using C = Type<NakedC>; |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 784 | using CFunctor = ConsStdFunction(ConsSignature(C, Args...)); |
| 785 | using CUniquePtrFunctor = ConsStdFunction(ConsSignature(ConsUniquePtr(C), Args...)); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 786 | using AnnotatedCUniquePtr = SignatureType(AnnotatedSignature); |
| 787 | using AnnotatedC = CopyAnnotation(AnnotatedCUniquePtr, C); |
| 788 | using AnnotatedCFunctor = CopyAnnotation(AnnotatedCUniquePtr, CFunctor); |
| 789 | using AnnotatedCUniquePtrFunctor = CopyAnnotation(AnnotatedCUniquePtr, CUniquePtrFunctor); |
| 790 | using AnnotatedCFunctorRef = CopyAnnotation(AnnotatedCUniquePtr, ConsReference(CFunctor)); |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 791 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 792 | using ProvidedSignature = ConsSignature(AnnotatedCUniquePtrFunctor, AnnotatedCFunctorRef); |
| 793 | using LambdaSignature = ConsSignature(CUniquePtrFunctor, ConsReference(CFunctor)); |
| 794 | |
| 795 | using F1 = ComponentFunctor(EnsureProvidedType, TargetRequirements, AnnotatedCFunctor); |
| 796 | using F2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, LambdaSignature); |
| 797 | using F3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, LambdaSignature); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 798 | using R = Call(ComposeFunctors(F1, F2, F3), Comp); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 799 | struct Op { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 800 | using Result = Eval<GetResult(R)>; |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 801 | void operator()(ComponentStorage& storage) { |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 802 | auto provider = [](UnwrapType<Eval<CFunctor>>& fun) { |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 803 | return UnwrapType<Eval<CUniquePtrFunctor>>([=](UnwrapType<Args>... args) { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 804 | NakedC* c = new NakedC(fun(args...)); |
| 805 | return std::unique_ptr<NakedC>(c); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 806 | }); |
| 807 | }; |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 808 | using RealF2 = ComponentFunctor(PreProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); |
| 809 | using RealF3 = ComponentFunctor(PostProcessRegisterProvider, ProvidedSignature, Type<decltype(provider)>); |
| 810 | using RealOp = Call(ComposeFunctors(F1, RealF2, RealF3), Comp); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 811 | FruitStaticAssert(IsSame(GetResult(RealOp), GetResult(R))); |
Marco Poletti | 3b95a51 | 2015-07-11 13:43:39 +0100 | [diff] [blame] | 812 | Eval<RealOp>()(storage); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 813 | } |
| 814 | }; |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 815 | |
| 816 | using ErrorHandler = AutoRegisterFactoryHelperErrorHandler<Eval<AnnotatedCFunctor>, Eval<AnnotatedCUniquePtrFunctor>>; |
| 817 | |
| 818 | // If we are about to report a NoBindingFound/NoBindingFoundForAbstractClass error for AnnotatedCFunctor, |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 819 | // report one for std::function<std::unique_ptr<C>(Args...)> instead, |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 820 | // otherwise we'd report an error about a type that the user doesn't expect. |
| 821 | using type = PropagateError(Catch(Catch(R, |
| 822 | NoBindingFoundErrorTag, ErrorHandler), |
| 823 | NoBindingFoundForAbstractClassErrorTag, ErrorHandler), |
| 824 | Op); |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 825 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 826 | |
Marco Poletti | 0e7e515 | 2016-05-14 09:20:05 +0100 | [diff] [blame] | 827 | // C has an Inject typedef, use it. unique_ptr case. |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 828 | template <typename Comp, typename TargetRequirements, typename unused, typename NakedC, typename AnnotatedSignature, typename... Args> |
| 829 | struct apply<Comp, TargetRequirements, None, Bool<true>, unused, Type<std::unique_ptr<NakedC>>, AnnotatedSignature, Args...> { |
Marco Poletti | 0e7e515 | 2016-05-14 09:20:05 +0100 | [diff] [blame] | 830 | using AnnotatedCUniquePtr = SignatureType(AnnotatedSignature); |
| 831 | using AnnotatedC = CopyAnnotation(AnnotatedCUniquePtr, RemoveUniquePtr(RemoveAnnotations(AnnotatedCUniquePtr))); |
| 832 | using DecoratedSignatureReturningValue = GetInjectAnnotation(AnnotatedC); |
| 833 | using DecoratedSignature = ConsSignatureWithVector(AnnotatedCUniquePtr, |
| 834 | SignatureArgs(DecoratedSignatureReturningValue)); |
| 835 | using DecoratedSignatureArgs = SignatureArgs(DecoratedSignature); |
| 836 | using ActualSignatureInInjectionTypedef = ConsSignatureWithVector(SignatureType(DecoratedSignature), |
| 837 | RemoveNonAssisted(DecoratedSignatureArgs)); |
| 838 | using NonAssistedArgs = RemoveAssisted(DecoratedSignatureArgs); |
| 839 | |
| 840 | using F1 = ComponentFunctor(RegisterConstructorAsUniquePtrFactory, DecoratedSignature); |
| 841 | using F2 = ComponentFunctor(EnsureProvidedTypes, TargetRequirements, ExpandProvidersInParams(NonAssistedArgs)); |
| 842 | |
| 843 | using type = If(Not(IsSame(AnnotatedSignature, ActualSignatureInInjectionTypedef)), |
| 844 | ConstructError(FunctorSignatureDoesNotMatchErrorTag, AnnotatedSignature, ActualSignatureInInjectionTypedef), |
| 845 | Call(ComposeFunctors(F1, F2), Comp)); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 846 | }; |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 847 | |
| 848 | // C has an Inject typedef, use it. Value (not unique_ptr) case. |
Marco Poletti | f8cb4bc | 2016-03-26 11:45:59 +0000 | [diff] [blame] | 849 | template <typename Comp, typename TargetRequirements, typename unused, typename NakedC, typename AnnotatedSignature, typename... Args> |
| 850 | struct apply<Comp, TargetRequirements, None, Bool<true>, unused, Type<NakedC>, AnnotatedSignature, Args...> { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 851 | using AnnotatedC = SignatureType(AnnotatedSignature); |
| 852 | using DecoratedSignature = GetInjectAnnotation(AnnotatedC); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 853 | using DecoratedSignatureArgs = SignatureArgs(DecoratedSignature); |
| 854 | using ActualSignatureInInjectionTypedef = ConsSignatureWithVector(SignatureType(DecoratedSignature), |
| 855 | RemoveNonAssisted(DecoratedSignatureArgs)); |
| 856 | using NonAssistedArgs = RemoveAssisted(DecoratedSignatureArgs); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 857 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 858 | using F1 = ComponentFunctor(RegisterConstructorAsValueFactory, DecoratedSignature); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 859 | using F2 = ComponentFunctor(EnsureProvidedTypes, TargetRequirements, ExpandProvidersInParams(NonAssistedArgs)); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 860 | |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 861 | using type = If(Not(IsSame(AnnotatedSignature, ActualSignatureInInjectionTypedef)), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 862 | ConstructError(FunctorSignatureDoesNotMatchErrorTag, AnnotatedSignature, ActualSignatureInInjectionTypedef), |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 863 | Call(ComposeFunctors(F1, F2), Comp)); |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 864 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 865 | }; |
| 866 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 867 | struct AutoRegisterHelper { |
| 868 | |
| 869 | template <typename Comp, typename TargetRequirements, typename has_inject_annotation, typename AnnotatedC> |
Marco Poletti | da1bc0c | 2015-02-15 13:42:46 +0000 | [diff] [blame] | 870 | struct apply; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 871 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 872 | // C has an Inject typedef, use it. |
| 873 | template <typename Comp, typename TargetRequirements, typename AnnotatedC> |
| 874 | struct apply<Comp, TargetRequirements, Bool<true>, AnnotatedC> { |
| 875 | using Inject = GetInjectAnnotation(AnnotatedC); |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 876 | using CRequirements = ExpandProvidersInParams(SignatureArgs(Inject)); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 877 | using F = ComposeFunctors( |
| 878 | ComponentFunctor(PreProcessRegisterConstructor, Inject), |
| 879 | ComponentFunctor(PostProcessRegisterConstructor, Inject), |
| 880 | ComponentFunctor(EnsureProvidedTypes, TargetRequirements, CRequirements)); |
Marco Poletti | 7e8b15a | 2015-12-07 22:54:38 +0000 | [diff] [blame] | 881 | using type = Call(F, Comp); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 882 | }; |
| 883 | |
| 884 | |
| 885 | template <typename Comp, typename TargetRequirements, typename AnnotatedC> |
| 886 | struct apply<Comp, TargetRequirements, Bool<false>, AnnotatedC> { |
Marco Poletti | 66918a4 | 2017-01-01 11:17:57 +0100 | [diff] [blame] | 887 | using type = ConstructNoBindingFoundError(AnnotatedC); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 888 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 889 | }; |
| 890 | |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 891 | struct AutoRegister { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 892 | // The types in TargetRequirements will not be auto-registered. |
| 893 | template <typename Comp, typename TargetRequirements, typename AnnotatedC> |
| 894 | struct apply; |
| 895 | |
| 896 | // Tries to register C by looking for a typedef called Inject inside C. |
| 897 | template <typename Comp, typename TargetRequirements, typename AnnotatedC> |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 898 | struct apply { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 899 | using type = AutoRegisterHelper(Comp, |
| 900 | TargetRequirements, |
| 901 | HasInjectAnnotation(RemoveAnnotations(AnnotatedC)), |
| 902 | AnnotatedC); |
| 903 | }; |
| 904 | |
| 905 | template <typename Comp, typename TargetRequirements, typename NakedC, typename... NakedArgs> |
| 906 | struct apply<Comp, TargetRequirements, Type<std::function<NakedC(NakedArgs...)>>> { |
| 907 | using type = AutoRegisterFactoryHelper(Comp, |
| 908 | TargetRequirements, |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 909 | FindInMap(typename Comp::InterfaceBindings, Type<NakedC>), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 910 | HasInjectAnnotation(Type<NakedC>), |
| 911 | IsAbstract(Type<NakedC>), |
| 912 | Type<NakedC>, |
| 913 | Type<NakedC(NakedArgs...)>, |
| 914 | Id<RemoveAnnotations(Type<NakedArgs>)>...); |
| 915 | }; |
| 916 | |
| 917 | template <typename Comp, typename TargetRequirements, typename NakedC, typename... NakedArgs> |
| 918 | struct apply<Comp, TargetRequirements, Type<std::function<std::unique_ptr<NakedC>(NakedArgs...)>>> { |
| 919 | using type = AutoRegisterFactoryHelper(Comp, |
| 920 | TargetRequirements, |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 921 | FindInMap(typename Comp::InterfaceBindings, Type<NakedC>), |
Marco Poletti | 0e7e515 | 2016-05-14 09:20:05 +0100 | [diff] [blame] | 922 | HasInjectAnnotation(Type<NakedC>), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 923 | IsAbstract(Type<NakedC>), |
| 924 | Type<std::unique_ptr<NakedC>>, |
| 925 | Type<std::unique_ptr<NakedC>(NakedArgs...)>, |
| 926 | Id<RemoveAnnotations(Type<NakedArgs>)>...); |
| 927 | }; |
| 928 | |
| 929 | template <typename Comp, typename TargetRequirements, typename Annotation, typename NakedC, typename... NakedArgs> |
| 930 | struct apply<Comp, TargetRequirements, |
| 931 | Type<fruit::Annotated<Annotation, std::function<NakedC(NakedArgs...)>>>> { |
| 932 | using type = AutoRegisterFactoryHelper(Comp, |
| 933 | TargetRequirements, |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 934 | FindInMap(typename Comp::InterfaceBindings, |
| 935 | Type<fruit::Annotated<Annotation, NakedC>>), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 936 | HasInjectAnnotation(Type<NakedC>), |
| 937 | IsAbstract(Type<NakedC>), |
| 938 | Type<NakedC>, |
| 939 | Type<fruit::Annotated<Annotation, NakedC>(NakedArgs...)>, |
| 940 | Id<RemoveAnnotations(Type<NakedArgs>)>...); |
| 941 | }; |
| 942 | |
| 943 | template <typename Comp, typename TargetRequirements, typename Annotation, typename NakedC, typename... NakedArgs> |
| 944 | struct apply<Comp, TargetRequirements, |
| 945 | Type<fruit::Annotated<Annotation, std::function<std::unique_ptr<NakedC>(NakedArgs...)>>>> { |
| 946 | using type = AutoRegisterFactoryHelper(Comp, |
| 947 | TargetRequirements, |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 948 | FindInMap(typename Comp::InterfaceBindings, |
| 949 | Type<fruit::Annotated<Annotation, NakedC>>), |
Marco Poletti | 0e7e515 | 2016-05-14 09:20:05 +0100 | [diff] [blame] | 950 | HasInjectAnnotation(Type<NakedC>), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 951 | IsAbstract(Type<NakedC>), |
| 952 | Type<std::unique_ptr<NakedC>>, |
| 953 | Type<fruit::Annotated<Annotation, std::unique_ptr<NakedC>>(NakedArgs...)>, |
| 954 | Id<RemoveAnnotations(Type<NakedArgs>)>...); |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 955 | }; |
| 956 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 957 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 958 | struct EnsureProvidedTypeHelper { |
| 959 | template <typename Comp, typename TargetRequirements, |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 960 | typename is_already_provided_or_in_target_requirements, typename InterfaceBinding, |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 961 | typename AnnotatedC> |
| 962 | struct apply; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 963 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 964 | // Already provided or in target requirements, ok. |
| 965 | template <typename Comp, typename TargetRequirements, typename unused, typename AnnotatedC> |
| 966 | struct apply<Comp, TargetRequirements, Bool<true>, unused, AnnotatedC> { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 967 | using type = ComponentFunctorIdentity(Comp); |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 968 | }; |
| 969 | |
| 970 | // Has an interface binding. |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 971 | template <typename Comp, typename TargetRequirements, typename AnnotatedC, |
| 972 | typename AnnotatedI> |
| 973 | struct apply<Comp, TargetRequirements, Bool<false>, AnnotatedC, AnnotatedI> { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 974 | using F1 = ComponentFunctor(ProcessInterfaceBinding, AnnotatedI, AnnotatedC); |
| 975 | using F2 = ComponentFunctor(EnsureProvidedType, TargetRequirements, AnnotatedC); |
| 976 | using type = Call(ComposeFunctors(F1, F2), Comp); |
| 977 | }; |
| 978 | |
| 979 | // Not yet provided, nor in target requirements, nor in InterfaceBindings. Try auto-registering. |
| 980 | template <typename Comp, typename TargetRequirements, typename AnnotatedC> |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 981 | struct apply<Comp, TargetRequirements, Bool<false>, None, AnnotatedC> { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 982 | using type = AutoRegister(Comp, TargetRequirements, AnnotatedC); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 983 | }; |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 984 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 985 | |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 986 | struct EnsureProvidedType { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 987 | template <typename Comp, typename TargetRequirements, typename AnnotatedT> |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 988 | struct apply { |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 989 | using AnnotatedC = NormalizeType(AnnotatedT); |
| 990 | using type = EnsureProvidedTypeHelper(Comp, |
| 991 | TargetRequirements, |
Marco Poletti | e5c936b | 2015-07-25 11:24:27 +0100 | [diff] [blame] | 992 | Or(IsInSet(AnnotatedC, typename Comp::Ps), |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 993 | IsInSet(AnnotatedC, TargetRequirements)), |
| 994 | FindInMap(typename Comp::InterfaceBindings, AnnotatedC), |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 995 | AnnotatedC); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 996 | }; |
Marco Poletti | ca50c3a | 2014-12-31 18:26:52 +0100 | [diff] [blame] | 997 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 998 | |
Marco Poletti | 010daa6 | 2015-07-06 01:15:12 +0100 | [diff] [blame] | 999 | struct EnsureProvidedTypes { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 1000 | template <typename Comp, typename TargetRequirements, typename TypeVector> |
Marco Poletti | e464713 | 2015-05-31 14:35:27 +0100 | [diff] [blame] | 1001 | struct apply { |
Marco Poletti | 36253c9 | 2015-07-19 17:12:47 +0100 | [diff] [blame] | 1002 | struct Helper { |
| 1003 | template <typename CurrentResult, typename T> |
| 1004 | struct apply { |
| 1005 | using type = Compose2ComponentFunctors(ComponentFunctor(EnsureProvidedType, TargetRequirements, T), |
| 1006 | CurrentResult); |
| 1007 | }; |
| 1008 | }; |
| 1009 | |
| 1010 | using type = Call(FoldVector(TypeVector, Helper, ComponentFunctorIdentity), |
| 1011 | Comp); |
Marco Poletti | b9f19bf | 2015-01-01 17:07:25 +0100 | [diff] [blame] | 1012 | }; |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 1013 | }; |
| 1014 | |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1015 | struct ProcessBinding { |
| 1016 | template <typename Binding> |
| 1017 | struct apply; |
| 1018 | |
| 1019 | template <typename I, typename C> |
Marco Poletti | 0109baa | 2016-03-25 13:04:47 +0000 | [diff] [blame] | 1020 | struct apply<fruit::impl::Bind<I, C>> { |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1021 | using type = ComponentFunctor(AddDeferredInterfaceBinding, Type<I>, Type<C>); |
| 1022 | }; |
| 1023 | |
| 1024 | template <typename Signature> |
Marco Poletti | 0109baa | 2016-03-25 13:04:47 +0000 | [diff] [blame] | 1025 | struct apply<fruit::impl::RegisterConstructor<Signature>> { |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1026 | using type = ComponentFunctor(DeferredRegisterConstructor, Type<Signature>); |
| 1027 | }; |
| 1028 | |
Marco Poletti | 0acba69 | 2016-12-10 17:44:38 +0000 | [diff] [blame] | 1029 | template <typename AnnotatedC, typename C> |
| 1030 | struct apply<fruit::impl::BindInstance<AnnotatedC, C>> { |
| 1031 | using type = ComponentFunctor(RegisterInstance, Type<AnnotatedC>, Type<C>); |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1032 | }; |
| 1033 | |
| 1034 | template <typename Lambda> |
Marco Poletti | 0109baa | 2016-03-25 13:04:47 +0000 | [diff] [blame] | 1035 | struct apply<fruit::impl::RegisterProvider<Lambda>> { |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1036 | using type = ComponentFunctor(DeferredRegisterProvider, Type<Lambda>); |
| 1037 | }; |
| 1038 | |
| 1039 | template <typename AnnotatedSignature, typename Lambda> |
Marco Poletti | 0109baa | 2016-03-25 13:04:47 +0000 | [diff] [blame] | 1040 | struct apply<fruit::impl::RegisterProvider<AnnotatedSignature, Lambda>> { |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1041 | using type = ComponentFunctor(DeferredRegisterProviderWithAnnotations, Type<AnnotatedSignature>, Type<Lambda>); |
| 1042 | }; |
| 1043 | |
Marco Poletti | 0316a00 | 2016-08-29 16:43:10 +0100 | [diff] [blame] | 1044 | template <typename AnnotatedC> |
| 1045 | struct apply<fruit::impl::AddInstanceMultibinding<AnnotatedC>> { |
| 1046 | using type = ComponentFunctorIdentity; |
| 1047 | }; |
| 1048 | |
| 1049 | template <typename AnnotatedC> |
| 1050 | struct apply<fruit::impl::AddInstanceVectorMultibindings<AnnotatedC>> { |
| 1051 | using type = ComponentFunctorIdentity; |
| 1052 | }; |
| 1053 | |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1054 | template <typename I, typename C> |
Marco Poletti | 0109baa | 2016-03-25 13:04:47 +0000 | [diff] [blame] | 1055 | struct apply<fruit::impl::AddMultibinding<I, C>> { |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1056 | using type = ComponentFunctor(AddInterfaceMultibinding, Type<I>, Type<C>); |
| 1057 | }; |
| 1058 | |
| 1059 | template <typename Lambda> |
Marco Poletti | 0109baa | 2016-03-25 13:04:47 +0000 | [diff] [blame] | 1060 | struct apply<fruit::impl::AddMultibindingProvider<Lambda>> { |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1061 | using type = ComponentFunctor(RegisterMultibindingProvider, Type<Lambda>); |
| 1062 | }; |
| 1063 | |
| 1064 | template <typename AnnotatedSignature, typename Lambda> |
Marco Poletti | 0109baa | 2016-03-25 13:04:47 +0000 | [diff] [blame] | 1065 | struct apply<fruit::impl::AddMultibindingProvider<AnnotatedSignature, Lambda>> { |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1066 | using type = ComponentFunctor(RegisterMultibindingProviderWithAnnotations, Type<AnnotatedSignature>, Type<Lambda>); |
| 1067 | }; |
| 1068 | |
| 1069 | template <typename DecoratedSignature, typename Lambda> |
Marco Poletti | 0109baa | 2016-03-25 13:04:47 +0000 | [diff] [blame] | 1070 | struct apply<fruit::impl::RegisterFactory<DecoratedSignature, Lambda>> { |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1071 | using type = ComponentFunctor(RegisterFactory, Type<DecoratedSignature>, Type<Lambda>); |
| 1072 | }; |
| 1073 | |
| 1074 | template <typename... Params> |
Marco Poletti | 0109baa | 2016-03-25 13:04:47 +0000 | [diff] [blame] | 1075 | struct apply<fruit::impl::InstallComponent<fruit::Component<Params...>>> { |
Marco Poletti | cbe3c7a | 2016-02-07 09:52:02 +0000 | [diff] [blame] | 1076 | using type = ComponentFunctor(InstallComponentHelper, Type<Params>...); |
| 1077 | }; |
| 1078 | }; |
| 1079 | |
Marco Poletti | a19fd1e | 2015-03-07 18:50:37 +0000 | [diff] [blame] | 1080 | } // namespace meta |
Marco Poletti | 4d39c58 | 2014-11-24 18:33:48 +0000 | [diff] [blame] | 1081 | } // namespace impl |
| 1082 | } // namespace fruit |
| 1083 | |
| 1084 | |
| 1085 | #endif // FRUIT_COMPONENT_FUNCTORS_DEFN_H |