/* * Copyright 2014 Google Inc. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef FRUIT_INJECTOR_DEFN_H #define FRUIT_INJECTOR_DEFN_H #include // Redundant, but makes KDevelop happy. #include namespace fruit { template template inline Injector::Injector(Component (*getComponent)(FormalArgs...), Args&&... args) { Component component = fruit::createComponent().install(getComponent, std::forward(args)...); fruit::impl::MemoryPool memory_pool; using exposed_types_t = std::vector>; exposed_types_t exposed_types = exposed_types_t(std::initializer_list{fruit::impl::getTypeId

()...}, fruit::impl::ArenaAllocator(memory_pool)); storage = std::unique_ptr( new fruit::impl::InjectorStorage(std::move(component.storage), exposed_types, memory_pool)); } namespace impl { namespace meta { template struct InjectorImplHelper { // This performs all checks needed in the constructor of Injector that takes NormalizedComponent. template struct CheckConstructionFromNormalizedComponent { using Op = InstallComponent(Comp, NormalizedComp); // The calculation of MergedComp will also do some checks, e.g. multiple bindings for the same type. using MergedComp = GetResult(Op); using TypesNotProvided = SetDifference(RemoveConstFromTypes(Vector...>), GetComponentPs(MergedComp)); using MergedCompRs = SetDifference(GetComponentRsSuperset(MergedComp), GetComponentPs(MergedComp)); using type = Eval...>)), GetComponentPs(MergedComp))), ConstructErrorWithArgVector(TypesInInjectorNotProvidedErrorTag, SetToVector(TypesNotProvided)), If(Not(IsContained(VectorToSetUnchecked(RemoveConstTypes(Vector...>)), GetComponentNonConstRsPs(MergedComp))), ConstructErrorWithArgVector( TypesInInjectorProvidedAsConstOnlyErrorTag, SetToVector(SetDifference(VectorToSetUnchecked(RemoveConstTypes(Vector...>)), GetComponentNonConstRsPs(MergedComp)))), None))))>; }; template struct CheckGet { using Comp = ConstructComponentImpl(Type

...); using type = Eval)), If(Not(IsInSet(NormalizeType(Type), GetComponentPs(Comp))), ConstructError(TypeNotProvidedErrorTag, Type), If(And(TypeInjectionRequiresNonConstBinding(Type), Not(IsInSet(NormalizeType(Type), GetComponentNonConstRsPs(Comp)))), ConstructError(TypeProvidedAsConstOnlyErrorTag, Type), None)))>; }; }; } // namespace meta } // namespace impl template template inline Injector::Injector(const NormalizedComponent& normalized_component, Component (*getComponent)(FormalArgs...), Args&&... args) { Component component = fruit::createComponent().install(getComponent, std::forward(args)...); fruit::impl::MemoryPool memory_pool; storage = std::unique_ptr(new fruit::impl::InjectorStorage( *(normalized_component.storage.storage), std::move(component.storage), memory_pool)); using NormalizedComp = fruit::impl::meta::ConstructComponentImpl(fruit::impl::meta::Type...); using Comp1 = fruit::impl::meta::ConstructComponentImpl(fruit::impl::meta::Type...); // We don't check whether the construction of NormalizedComp or Comp resulted in errors here; if they did, the // instantiation // of NormalizedComponent or Component would have resulted in an // error already. using E = typename fruit::impl::meta::InjectorImplHelper::template CheckConstructionFromNormalizedComponent< NormalizedComp, Comp1>::type; (void)typename fruit::impl::meta::CheckIfError::type(); } template template inline fruit::impl::RemoveAnnotations Injector::get() { using E = typename fruit::impl::meta::InjectorImplHelper::template CheckGet::type; (void)typename fruit::impl::meta::CheckIfError::type(); return storage->template get(); } template template inline Injector::operator T() { return get(); } template template inline const std::vector*>& Injector::getMultibindings() { using Op = fruit::impl::meta::Eval>)>; (void)typename fruit::impl::meta::CheckIfError::type(); return storage->template getMultibindings(); } template FRUIT_DEPRECATED_DEFINITION(inline void Injector::eagerlyInjectAll()) { // Eagerly inject normal bindings. void* unused[] = {reinterpret_cast( storage->template get)>>>())...}; (void)unused; storage->eagerlyInjectMultibindings(); } } // namespace fruit #endif // FRUIT_INJECTOR_DEFN_H