text: /*
   * 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_COMPONENT_H
  #define FRUIT_COMPONENT_H
  
  // This include is not required here, but having it here shortens the include trace in error messages.
  #include <fruit/impl/injection_errors.h>
  
  #include <fruit/fruit_forward_decls.h>
  #include <fruit/impl/bindings.h>
  #include <fruit/impl/component_functors.defn.h>
  #include <fruit/impl/component_storage/component_storage.h>
  #include <fruit/impl/component_storage/partial_component_storage.h>
  #include <fruit/impl/meta/component.h>
  
  namespace fruit {
  
  /**
   * A component (aka module) represents a collection of bindings.
   * You can think of a Component object as a UML component.
   *
   * The parameters can be of the form <P...> or <Required<R...>, P...> where:
   * * R... are the required types (types required to inject some types in P... but that are not provided by this
   *   Component), if any
   * * P... are the types provided by this Component.
   * No type can appear twice, not even once in R and once in P.
   *
   * See PartialComponent below for how to construct a Component.
   */
  template <typename... Params>
  class Component {
  public:
    Component(Component&&) noexcept = default;
  
    Component& operator=(Component&&) = delete;
    Component& operator=(const Component&) = delete;
  
    /**
     * Converts a PartialComponent to an arbitrary Component, auto-injecting the missing types (if
     * any).
     * This is usually called implicitly when returning a component from a function. See PartialComponent for an example.
     */
    template <typename... Bindings>
    Component(PartialComponent<Bindings...>&& component) noexcept; // NOLINT(google-explicit-constructor)
  
  private:
    // Do not use. Use fruit::createComponent() instead.
    Component() = default;
  
    template <typename... Types>
    friend class Component;
  
    template <typename... Bindings>
    friend class PartialComponent;
  
    template <typename... OtherParams>
    friend class NormalizedComponent;
  
    template <typename... OtherParams>
    friend class Injector;
  
    template <typename... Bindings>
    friend class fruit::impl::PartialComponentStorage;
  
    template <typename Component, typename... Args>
    friend class fruit::impl::LazyComponentImpl;
  
    friend struct fruit::impl::ComponentStorageEntry::LazyComponentWithNoArgs;
  
    template <typename Component, typename... Args>
    friend class fruit::impl::ComponentInterfaceImpl;
  
    fruit::impl::ComponentStorage storage;
  
    using Comp = fruit::impl::meta::Eval<fruit::impl::meta::ConstructComponentImpl(fruit::impl::meta::Type<Params>...)>;
  
    using Check1 = typename fruit::impl::meta::CheckIfError<Comp>::type;
    // Force instantiation of Check1.
    static_assert(true || sizeof(Check1), "");
  };
  
  /**
   * Constructs an empty component.
   *
   * Example usage:
   *
   * fruit::Component<Foo> getFooComponent() {
   *   return fruit::createComponent()
   *      .install(getComponent1)
   *      .install(getComponent2)
   *      .bind<Foo, FooImpl>();
   * }
   *
   * Since types are auto-injected when needed, just converting this to the desired component can suffice in some cases,
   * e.g.:
   *
   * fruit::Component<Foo> getFooComponent() {
   *   return fruit::createComponent();
   * }
   *
   * That works if Foo has an Inject typedef or a constructor wrapped in INJECT.
   */
  PartialComponent<> createComponent();
  
  /**
   * A partially constructed component.
   *
   * Client code should never write `PartialComponent'; always start the construction of a component with
   * fruit::createComponent(), and end it by casting the PartialComponent to the desired Component (often done implicitly
   * by returning a PartialComponent from a function that has Component<...> as the return type).
   *
   * The template parameter is used to propagate information about bound types, it is purely an implementation detail;
   * users of the Fruit library can pretend that this class is not templated, in no case a specific template parameter is
   * required. All methods of this class return a PartialComponent, which allows to chain method invocations without
   * declaring a variable of type PartialComponent.
   *
   * Example usage:
   *
   * fruit::Component<Foo> getFooComponent() {
   *   return fruit::createComponent()
   *      .install(getComponent1)
   *      .install(getComponent2)
   *      .bind<Foo, FooImpl>();
   * }
   *
   * Note that no variable of type PartialComponent has been declared; this class should only be used for temporary
   * values.
   */
  template <typename... Bindings>
  class PartialComponent {
  public:
    PartialComponent& operator=(PartialComponent&&) = delete;
    PartialComponent& operator=(const PartialComponent&) = delete;
  
    /**
     * This tells Fruit that "the implementation of I is C".
     * I must be a base class of C, and it's typically (but not necessarily) an abstract class.
     * C is typically a concrete class, but it doesn't have to be: for example, if A inherits from B and B inherits from C
     * you can specify bind<C, B>() and bind<B, A>().
     *
     * The most common use of this is to bind the type I to the type C, for example:
     *
     * class MyInterface {
     * public:
     *   virtual void foo() = 0;
     * };
     *
     * class MyImplementation {
     * public:
     *   INJECT(MyImplementation()) {}
     *
     *   void foo() {
     *     ...
     *   }
     * };
     *
     * fruit::Component<MyInterface> getMyInterfaceComponent() {
     *   return fruit::createComponent()
     *      .bind<MyInterface, MyImplementation>();
     * }
     *
     * The implementation class can be bound in any way, it doesn't need to be bound using constructor injection as above
     * (although that's a very common use case).
     *
     * You can bind an interface to a type bound using a constant binding (see the bindInstance method that takes a const&
     * for more details), however the interface will then also be considered bound with a constant binding, and you must
     * declare that in the returned Component's type. For example:
     *
     * fruit::Component<const MyInterface> getMyInterfaceComponent() {
     *   static const MyImplementation my_implementation = MyImplementation();
     *   return fruit::createComponent()
     *      .bindInstance(my_implementation)
     *      .bind<MyInterface, MyImplementation>();
     * }
     *
     * In addition to binding the type I to the type C, a `bind()` can also be used to bind a
     * std::function<std::unique_ptr<I>(Args...)> to a std::function<std::unique_ptr<C>(Args...)> or a
     * std::function<C(Args...)>. For example:
     *
     * fruit::Component<std::function<std::unique_ptr<MyInterface>(int)>> getIFactoryComponent() {
     *   static const std::function<MyImplementation(int)> cFactory = [](int n) { return MyImplementation(n); };
     *   return fruit::createComponent()
     *       .bind<MyInterface, MyImplementation>()
     *       .bindInstance(cFactory);
     * }
     *
     * Or alternatively you can do the same using constructor injection:
     *
     * class MyImplementation {
     * public:
     *   INJECT(MyImplementation(ASSISTED(int) n))
     *     : n(n) {
     *   }
     *   ...
     * };
     *
     * fruit::Component<std::function<std::unique_ptr<MyInterface>(int)>> getIFactoryComponent() {
     *   return fruit::createComponent()
     *       .bind<MyInterface, MyImplementation>();
     * }
     *
     * Fruit determines the actual binding(s) to generate based on the types you declare as provided in the returned
     * Component<> type (e.g. in the last example std::function<std::unique_ptr<MyInterface>(int)> is declared as provided
     * so Fruit will generate a factory binding instead of a normal MyInterface->MyImplementation binding.
     *
     * Fruit can also detect types that are needed for constructor/provider/factory bindings, and it will then use that
     * information to determine the desired binding. For example:
     *
     * class MyImplementation {
     * public:
     *   INJECT(MyImplementation(ASSISTED(int) n))
     *     : n(n) {
     *   }
     *   ...
     * };
     *
     * class Foo {
     * private:
     *   std::function<std::unique_ptr<MyInterface>(int)> factory;
     * public:
     *   INJECT(Foo(std::function<std::unique_ptr<MyInterface>(int)> factory))
     *     : factory(factory) {
     *   }
     * };
     *
     * fruit::Component<Foo> getIFactoryComponent() {
     *   return fruit::createComponent()
     *       // We want to bind Foo, which requires std::function<std::unique_ptr<MyInterface>(int)>.
     *       // So std::function<std::unique_ptr<MyInterface>(int)> will be bound to
     *       // std::function<std::unique_ptr<MyImplementation>(int)>, and that will be bound using constructor injection.
     *       .bind<MyInterface, MyImplementation>();
     * }
     *
     * All these cases support annotated injection, just wrap I and/or C in fruit::Annotated<> if desired. For example:
     *
     * struct MyAnnotation{};
     *
     * fruit::Component<fruit::Annotated<MyAnnotation, MyInterface>> getMyInterfaceComponent() {
     *   return fruit::createComponent()
     *      .bind<fruit::Annotated<MyAnnotation, MyInterface>, MyImplementation>();
     * }
     */
    template <typename I, typename C>
    PartialComponent<fruit::impl::Bind<I, C>, Bindings...> bind();
  
    /**
     * Registers Signature as the constructor signature to use to inject a type.
     *
     * Example usage:
     *
     * fruit::createComponent()
     *     .registerConstructor<Foo(Bar*,Baz*)>() // Registers the constructor Foo::Foo(Bar*,Baz*)
     *
     * It's usually more convenient to use an INJECT macro or Inject typedef instead, e.g.:
     *
     * class Foo {
     * public:
     *   // This also declares the constructor
     *   INJECT(Foo(Bar* bar, Baz* baz));
     * ...
     * };
     *
     * or (equivalent):
     *
     * class Foo {
     * public:
     *   using Inject = Foo(Bar*, Baz*);
     *   Foo(Bar* bar, Baz* baz);
     * ...
     * };
     *
     * Use registerConstructor() when you want to inject the class C in different ways in different components (just make
     * sure those don't end up in the same injector, or use annotated injection to prevent the bindings from clashing),
     * or when C is a third-party class that can't be modified.
     *
     * This supports annotated injection, just wrap the desired types (return type and/or argument types of the signature)
     * with fruit::Annotated<> if desired. For example:
     *
     * struct Annotation1 {};
     * struct Annotation2 {};
     *
     * struct Foo {
     *   Foo(Bar* bar) {...}
     * };
     *
     * fruit::Component<fruit::Annotated<Annotation1, Bar>> getBarComponent() {...}
     *
     * fruit::Component<fruit::Annotated<Annotation2, Foo>> getFooComponent() {
     *   return fruit::createComponent()
     *       .install(getBarComponent)
     *       .registerConstructor<fruit::Annotated<Annotation2, Foo>(fruit::Annotated<Annotation1, Bar*>)>();
     * }
     *
     * This does *not* support assisted injection, for that you should use registerFactory() instead.
     *
     * The allowed argument types in the signature are, for any class (or fundamental) type C:
     *
     * C
     * C*
     * C&
     * const C*
     * const C&
     * shared_ptr<C>
     * Provider<C>
     * Provider<const C>
     * Annotated<Annotation, C>                   (for any type `Annotation')
     * Annotated<Annotation, C*>                  (for any type `Annotation')
     * Annotated<Annotation, C&>                  (for any type `Annotation')
     * Annotated<Annotation, const C*>            (for any type `Annotation')
     * Annotated<Annotation, const C&>            (for any type `Annotation')
     * Annotated<Annotation, shared_ptr<C>>       (for any type `Annotation')
     * Annotated<Annotation, Provider<C>>         (for any type `Annotation')
     * Annotated<Annotation, Provider<const C>>   (for any type `Annotation')
     */
    template <typename Signature>
    PartialComponent<fruit::impl::RegisterConstructor<Signature>, Bindings...> registerConstructor();
  
    /**
     * Use this method to bind the type C to a specific instance.
     * The caller must ensure that the provided reference is valid for the entire lifetime of the component and of any
     * components or injectors that install this component; the caller must also ensure that the object is destroyed after
     * the last components/injectors using it are destroyed.
     *
     * Example usage:
     *
     * Component<Request> getRequestComponent(Request* request) {
     *   return fruit::createComponent()
     *       .bindInstance(*request);
     * }
     *
     * NormalizedComponent<...> normalizedComponent = ...;
     * Request request;
     * Injector<...> injector(normalizedComponent,
     *                        getRequestComponent,
     *                        request));
     *
     * This should be used sparingly (you should let Fruit handle the object lifetime when possible), but in some cases it
     * is necessary; for example, if a web server creates an injector to handle each request, this method can be used to
     * inject the request itself as in the example above (see the Server page in the Fruit tutorial for more details).
     *
     * It's also possible to bind constants, see the documentation of the bindInstance() method taking a const& for
     * details.
     */
    template <typename C>
    PartialComponent<fruit::impl::BindInstance<C, C>, Bindings...> bindInstance(C& instance);
  
    /**
     * Similar to the previous, but binds a const&. Note that the reference must still outlive the component/injector
     * as in the non-const case.
     * When using this method, you must declare that the type is constant in the Component type. For example:
     *
     * Component<const MyExpensiveClass> getMyExpensiveClassComponent() {
     *   static const MyExpensiveClass my_expensive_class = createMyExpensiveClass();
     *   return fruit::createComponent()
     *       .bindInstance(my_expensive_class);
     * }
     *
     * Constant bindings can be used as other bindings, except that you can only inject the constant type (e.g. as a
     * constructor parameter) as:
     *
     * C
     * const C*
     * const C&
     * Provider<const C>
     * Annotated<Annotation, C>                   (for any type `Annotation')
     * Annotated<Annotation, const C*>            (for any type `Annotation')
     * Annotated<Annotation, const C&>            (for any type `Annotation')
     * Annotated<Annotation, Provider<const C>>   (for any type `Annotation')
     *
     * While you can't inject it as:
     *
     * C*
     * C&
     * shared_ptr<C>
     * Provider<C>
     * Annotated<Annotation, C*>                  (for any type `Annotation')
     * Annotated<Annotation, C&>                  (for any type `Annotation')
     * Annotated<Annotation, shared_ptr<C>>       (for any type `Annotation')
     * Annotated<Annotation, Provider<C>>         (for any type `Annotation')
     */
    template <typename C>
    PartialComponent<fruit::impl::BindConstInstance<C, C>, Bindings...> bindInstance(const C& instance);
  
    /**
     * This is deleted to catch cases where the instance would likely be destroyed before the component/injectors.
     */
    template <typename C>
    PartialComponent<fruit::impl::BindConstInstance<C, C>, Bindings...> bindInstance(C&&) = delete;
  
    /**
     * Similar to the first version of bindInstance(), but allows to specify an annotated type that
     * will be bound to the specified value.
     * For example, to bind an instance to the type fruit::Annotated<Hostname, std::string>, you can use:
     *
     * fruit::Component<fruit::Annotated<Hostname, std::string>> getHostnameComponent(std::string* hostname) {
     *   fruit::createComponent()
     *       .bindInstance<fruit::Annotated<Hostname, std::string>>(*hostname);
     * }
     */
    template <typename AnnotatedType, typename C>
    PartialComponent<fruit::impl::BindInstance<AnnotatedType, C>, Bindings...> bindInstance(C& instance);
  
    /**
     * Similar to the previous, but binds a const&. Example usage:
     *
     * fruit::Component<fruit::Annotated<Hostname, const std::string>> getHostnameComponent() {
     *   static const std::string hostname = determineHostname();
     *   fruit::createComponent()
     *       .bindInstance<fruit::Annotated<Hostname, std::string>>(hostname);
     * }
     *
     * See the documentation for the bindInstance() overload that takes a non-annotated const& for more details.
     */
    template <typename AnnotatedType, typename C>
    PartialComponent<fruit::impl::BindConstInstance<AnnotatedType, C>, Bindings...> bindInstance(const C& instance);
  
    /**
     * This is deleted to catch cases where the instance would likely be destroyed before the component/injectors.
     */
    template <typename AnnotatedType, typename C>
    PartialComponent<fruit::impl::BindConstInstance<AnnotatedType, C>, Bindings...> bindInstance(C&& instance);
  
    /**
     * Registers `provider' as a provider of C, where provider is a lambda with no captures returning either C or C*
     * (prefer returning a C by value instead of allocating a C using `new C', to avoid the allocation).
     *
     * When injecting a C, the arguments of the provider will be injected and the provider will then be called to create
     * the C instance, that will then be stored in the injector.
     *
     * If `provider' returns a pointer, it must be non-null; otherwise the program will abort.
     *
     * Example:
     *
     * fruit::Component<Foo> getFooComponent() {
     *   return fruit::createComponent()
     *       .install(getBarComponent)
     *       .install(getBazComponent)
     *       .registerProvider([](Bar* bar, Baz* baz) {
     *          Foo foo(bar, baz);
     *          foo.initialize();
     *          return foo;
     *       });
     * }
     *
     * As in the previous example, it's not necessary to specify the type parameter, it will be inferred by the compiler.
     *
     * registerProvider() can't be called with a plain function, but you can write a lambda that wraps the function to
     * achieve the same result.
     *
     * Registering stateful functors (including lambdas with captures) is NOT supported.
     * However, you can write something like:
     *
     * struct Functor {
     *   Functor(int n) {...}
     *   MyClass operator()(Foo* foo) const {...}
     * };
     *
     * Component<MyClass> getMyClassComponent() {
     *   static const Functor aFunctor(42);
     *   return fruit::createComponent()
     *       .install(getFooComponent)
     *       .bindInstance(aFunctor)
     *       .registerProvider([](const Functor& functor, Foo* foo) { return functor(foo); });
     * }
     */
    template <typename Lambda>
    PartialComponent<fruit::impl::RegisterProvider<Lambda>, Bindings...> registerProvider(Lambda lambda);
  
    /**
     * Similar to the previous version of registerProvider(), but allows to specify an annotated type
     * for the provider. This allows to inject annotated types in the parameters and/or bind the
     * provider to an annotated type. For example:
     *
     * struct MyAnnotation1 {};
     * struct MyAnnotation2 {};
     *
     * Component<fruit::Annotated<Annotation1, Bar>> getBarComponent() {...}
     * Component<Baz> getBazComponent() {...}
     *
     * fruit::Component<fruit::Annotated<Annotation2, Foo>> getFooComponent() {
     *   return fruit::createComponent()
     *       .install(getBarComponent)
     *       .install(getBazComponent)
     *       .registerProvider<
     *           fruit::Annotated<Annotation2, Foo>(
     *               fruit::Annotated<Annotation1, Bar*>,
     *               Baz*)
     *           >([](Bar* bar, Baz* baz) {
     *              Foo foo(bar, baz);
     *              foo.initialize();
     *              return foo;
     *           });
     * }
     */
    template <typename AnnotatedSignature, typename Lambda>
    PartialComponent<fruit::impl::RegisterProvider<AnnotatedSignature, Lambda>, Bindings...>
    registerProvider(Lambda lambda);
  
    /**
     * Similar to bind<I, C>(), but adds a multibinding instead.
     *
     * Multibindings are independent from bindings; creating a binding with bind doesn't count as a multibinding, and
     * adding a multibinding doesn't allow to inject the type (it only allows to retrieve multibindings through the
     * getMultibindings method of the injector).
     *
     * Unlike bindings, where adding a the same binding twice is allowed (and ignored), adding the same multibinding
     * multiple times will result in the creation of multiple "equivalent" instances, that will all be returned by
     * getMultibindings().
     *
     * Another difference compared with normal bindings is that this can't be used to bind  a
     * std::function<std::unique_ptr<I>(Args...)> to a std::function<std::unique_ptr<C>(Args...)> or a
     * std::function<C(Args...)>.
     *
     * As bind(), this supports annotated injection, just wrap I and/or C in fruit::Annotated<> if desired. See the
     * documentation of bind() for more details.
     */
    template <typename I, typename C>
    PartialComponent<fruit::impl::AddMultibinding<I, C>, Bindings...> addMultibinding();
  
    /**
     * Similar to bindInstance(), but adds a multibinding instead.
     *
     * Multibindings are independent from bindings; creating a binding with bindInstance doesn't count as a
     * multibinding, and adding a multibinding doesn't allow to inject the type (it only allows to retrieve
     * multibindings through the getMultibindings method of the injector).
     *
     * Unlike bindings, where adding a the same binding twice is allowed (and ignored), adding several multibindings for
     * the same instance will result in duplicated values in the result of getMultibindings.
     *
     * Another difference compared to bindInstance() is that you can't use this to bind a const& (note that there is no
     * overload of this method that takes a const&).
     *
     * This method adds a multibinding for C. If the object implements an interface I and you want to add a multibinding
     * for that interface instead, you must cast the object to I& before passing it to this method.
     *
     * Note that this takes the instance by reference, not by value; it must remain valid for the entire lifetime of this
     * component and of any injectors created from this component.
     *
     * Example use:
     *
     * class MyClass {
     *   ...
     * };
     *
     * fruit::Component<> getMyComponent() {
     *   static MyClass x = MyClass(...);
     *   static MyClass y = MyClass(...);
     *   return fruit::createComponent()
     *       .addInstanceMultibinding(x)
     *       .addInstanceMultibinding(y);
     * }
     *
     * fruit::Injector<> injector(getMyComponent);
     * // This vector contains {&x, &y}.
     * const std::vector<MyClass*>& objects = injector.getMultibindings<MyClass>();
     */
    template <typename C>
    PartialComponent<fruit::impl::AddInstanceMultibinding<C>, Bindings...> addInstanceMultibinding(C& instance);
  
    /**
     * Similar to the previous version of addInstanceMultibinding(), but allows to specify an
     * annotated type.
     * Example use:
     *
     * struct MyAnnotation {};
     *
     * class MyClass {
     *   ...
     * };
     *
     * fruit::Component<> getMyComponent() {
     *   static MyClass x = MyClass(...);
     *   static MyClass y = MyClass(...);
     *   return fruit::createComponent()
     *       .addInstanceMultibinding<fruit::Annotated<MyAnnotation, MyClass>>(x)
     *       .addInstanceMultibinding<fruit::Annotated<MyAnnotation, MyClass>>(y);
     * }
     *
     * fruit::Injector<> injector(getMyComponent);
     * // This vector contains {&x, &y}.
     * const std::vector<MyClass*>& objects = injector.getMultibindings<fruit::Annotated<MyAnnotation, MyClass>>();
     */
    template <typename AnnotatedC, typename C>
    PartialComponent<fruit::impl::AddInstanceMultibinding<AnnotatedC>, Bindings...> addInstanceMultibinding(C& instance);
  
    /**
     * Equivalent to calling addInstanceMultibinding() for each elements of `instances'.
     * See the documentation of addInstanceMultibinding() for more details.
     *
     * Note that this takes the vector by reference, not by value; the vector (and its elements) must remain valid for the
     * entire lifetime of this component and of any injectors created from this component.
     *
     * Example use:
     *
     * class MyClass {
     *   ...
     * };
     *
     * fruit::Component<> getMyComponent() {
     *   static MyClass x = MyClass(...);
     *   static std::vector<MyClass> other_objects{MyClass(...), MyClass(...)};
     *   return fruit::createComponent()
     *       .addInstanceMultibinding(x)
     *       .addInstanceMultibindings(other_objects);
     * }
     *
     * fruit::Injector<> injector(getMyComponent);
     * // This vector contains {&x, &(other_objects[0]), &(other_objects[1])}.
     * const std::vector<MyClass*>& objects = injector.getMultibindings<MyClass>();
     */
    template <typename C>
    PartialComponent<fruit::impl::AddInstanceVectorMultibindings<C>, Bindings...>
    addInstanceMultibindings(std::vector<C>& instances);
  
    /**
     * Similar to the previous version of addInstanceMultibindings(), but it allows to specify an annotated type.
     *
     * Example use:
     *
     * class MyClass {
     *   ...
     * };
     *
     * fruit::Component<> getMyComponent() {
     *   static MyClass x = MyClass(...);
     *   static std::vector<MyClass> other_objects{MyClass(...), MyClass(...)};
     *   return fruit::createComponent()
     *       .addInstanceMultibinding<fruit::Annotated<MyAnnotation, MyClass>>(x)
     *       .addInstanceMultibindings<fruit::Annotated<MyAnnotation, MyClass>>(other_objects);
     * }
     *
     * fruit::Injector<> injector(getMyComponent);
     * // This vector contains {&x, &(other_objects[0]), &(other_objects[1])}.
     * const std::vector<MyClass*>& objects = injector.getMultibindings<fruit::Annotated<MyAnnotation, MyClass>>();
     */
    template <typename AnnotatedC, typename C>
    PartialComponent<fruit::impl::AddInstanceVectorMultibindings<AnnotatedC>, Bindings...>
    addInstanceMultibindings(std::vector<C>& instances);
  
    /**
     * Similar to registerProvider, but adds a multibinding instead.
     *
     * Multibindings are independent from bindings; creating a binding with registerProvider doesn't count as a
     * multibinding, and adding a multibinding doesn't allow to inject the type (it only allows to retrieve multibindings
     * through the getMultibindings method of the injector).
     *
     * Unlike bindings, where adding a the same binding twice is allowed (and ignored), adding the same multibinding
     * provider multiple times will result in the creation of multiple "equivalent" instances, that will all be returned
     * by getMultibindings.
     * It is good practice to add the multibindings in a component that is "close" to the injector in the get*Component
     * call chain, to avoid adding the same multibinding more than once.
     *
     * Example use:
     *
     * class MyClass {
     * public:
     *   MyClass(int n) {...}
     * };
     *
     * fruit::Component<> getMyComponent() {
     *   return fruit::createComponent()
     *       .addMultibindingProvider([]() { return MyClass(10); })
     *       .addMultibindingProvider([]() { return MyClass(10); })
     *       .addMultibindingProvider([]() { return MyClass(20); });
     * }
     *
     * fruit::Injector<> injector(getMyComponent);
     * // This vector contains {&x, &y, &z} where x and y are MyClass objects constructed with 10 and z is a MyClass
     * // object constructed with 20.
     * const std::vector<MyClass*>& objects = injector.getMultibindings<MyClass>();
     *
     * Note that this method adds a multibinding for the type returned by the provider. If the returned object implements
     * an interface I and you want to add a multibinding for that interface instead, you should cast the pointer to I*
     * before returning it.
     */
    template <typename Lambda>
    PartialComponent<fruit::impl::AddMultibindingProvider<Lambda>, Bindings...> addMultibindingProvider(Lambda lambda);
  
    /**
     * Similar to the previous version of addMultibindingProvider(), but allows to specify an annotated type
     * for the provider. This allows to inject annotated types in the parameters and/or bind the
     * provider to an annotated type.
     *
     * Example use:
     *
     * struct MyAnnotation1 {};
     * struct MyAnnotation2 {};
     *
     * Component<fruit::Annotated<Annotation1, Bar>> getBarComponent() {...}
     * Component<Baz> getBazComponent() {...}
     *
     * fruit::Component<> getFooComponent() {
     *   return fruit::createComponent()
     *       .install(getBarComponent)
     *       .install(getBazComponent)
     *       .registerMultibindingProvider<
     *           fruit::Annotated<Annotation2, Foo>(
     *               fruit::Annotated<Annotation1, Bar*>,
     *               Baz*)
     *           >([](Bar* bar, Baz* baz) {
     *              Foo foo(bar, baz);
     *              foo.initialize();
     *              return foo;
     *           });
     * }
     *
     *
     * fruit::Injector<> injector(getFooComponent);
     * // This vector contains {&x} where x is an instance of Foo constructed using the lambda above, with injected
     * // instances of Bar and Baz.
     * const std::vector<MyClass*>& objects = injector.getMultibindings<fruit::Annotated<Annotation2, Foo>>();
     */
    template <typename AnnotatedSignature, typename Lambda>
    PartialComponent<fruit::impl::AddMultibindingProvider<AnnotatedSignature, Lambda>, Bindings...>
    addMultibindingProvider(Lambda lambda);
  
    /**
     * Registers `factory' as a factory of C, where `factory' is a lambda with no captures returning C.
     * This is typically used for assisted injection (but it can also be used if no parameters are assisted).
     *
     * C can be any class (or fundamental) type. If C is std::unique_ptr<T>, the factory together with a bind<I,C> in the
     * same component will automatically bind the corresponding std::function that returns a std::unique_ptr<I>.
     * See the documentation of bind() for more details.
     *
     * The returned type can't be a pointer type. If you don't want to return it by value, you should return a
     * std::unique_ptr instead.
     *
     * Example:
     *
     * Component<std::function<std::unique_ptr<MyClass>(int)>> getMyClassComponent() {
     *   fruit::createComponent()
     *       .install(getFooComponent)
     *       .registerFactory<std::unique_ptr<MyClass>(Foo*, fruit::Assisted<int>)>(
     *          [](Foo* foo, int n) {
     *              return std::unique_ptr<MyClass>(new MyClass(foo, n));
     *          });
     * }
     *
     * Injector<std::function<std::unique_ptr<MyClass>(int)>> injector(getMyClassComponent);
     *
     * std::function<std::unique_ptr<MyClass>(int)> factory(injector);
     * std::unique_ptr<MyClass> x = factory(42);
     *
     * The parameters marked as Assisted will become parameters of the std::function (in the same order), while the others
     * (e.g. Foo in the example above) will be injected.
     *
     * Unlike registerProvider(), where the signature is inferred, for this method the signature (including any Assisted
     * annotations) must be specified explicitly, while the second template parameter is inferred.
     *
     * If the only thing that the factory does is to call new and the constructor of the class, it's usually more
     * convenient to use an Inject typedef or INJECT macro instead, e.g. the following are equivalent to the above:
     *
     * class MyClass {
     * public:
     *    using Inject = MyClass(Foo*, Assisted<int>);
     *
     *    MyClass(Foo* foo, int n) {...}
     * };
     *
     * or:
     *
     * class MyClass {
     * public:
     *    INJECT(MyClass(Foo* foo, ASSISTED(int) n)) {...}
     * };
     *
     * Use registerFactory() when you want to inject the class in different ways in different components (just make sure
     * those don't end up in the same injector), or when MyClass is a third-party class that can't be modified.
     *
     * registerFactory() can't be called with a plain function, but you can write a lambda that wraps the function to
     * achieve the same result.
     *
     * Registering stateful functors (including lambdas with captures) is NOT supported.
     * However, you can write something like:
     *
     * struct Functor {
     *   Functor(float x) {...}
     *   std::unique_ptr<MyClass> operator()(Foo* foo, int n) {...}
     * };
     *
     * Component<std::function<std::unique_ptr<MyClass>(int)>> getMyClassComponent() {
     *   static const Functor aFunctor(42.0);
     *   return fruit::createComponent()
     *       ... // Bind Foo
     *       .bindInstance(aFunctor)
     *       .registerFactory<
     *           std::unique_ptr<MyClass>(
     *               Functor functor,
     *               Foo*,
     *               Assisted<int>)
     *           >([](Functor functor, Foo* foo, int n) {
     *               return functor(foo, n);
     *           });
     * }
     */
    template <typename DecoratedSignature, typename Factory>
    PartialComponent<fruit::impl::RegisterFactory<DecoratedSignature, Factory>, Bindings...>
    registerFactory(Factory factory);
  
    /**
     * Adds the bindings (and multibindings) in the Component obtained by calling fun(args...) to the current component.
     *
     * For example, these component functions:
     * fruit::Component<Foo> getComponent1();
     * fruit::Component<Bar> getComponent2(int n, std::string s);
     *
     * can be combined as:
     *
     * fruit::Component<Foo, Bar> getFooBarComponent() {
     *   return fruit::createComponent()
     *      .install(getComponent1)
     *      .install(getComponent2, 5, std::string("Hello"));
     * }
     *
     * If any `args` are provided, they must be:
     * - Copy-constructible
     * - Move-constructible
     * - Assignable
     * - Move-assignable
     * - Equality comparable (i.e., operator== must be defined for two values of that type)
     * - Hashable (i.e., std::hash must be defined for values of that type)
     *
     * Note that this only applies to `args`. E.g. in the example above `int` and `std::string` must satisfy this
     * requirement (and they do), but `Foo` and `Bar` don't need to.
     *
     * Args and FormalArgs (if any) must be the same types; or to be precise, each type in Args must be convertible into
     * the corresponding type in FormalArgs.
     *
     * A lambda with no captures can also be used as the first argument, for example:
     *
     * fruit::Component<Foo, Bar> getFooBarComponent() {
     *   return fruit::createComponent()
     *      .install([]() { return getComponent1(); })
     *      .install([](int n) { return getComponent2(n, std::string("Hello")); }, 5);
     * }
     *
     * These two install() calls are equivalent to the previous ones.
     *
     * As in the example, the template parameters for this method will be inferred by the compiler, it's not necessary to
     * specify them explicitly.
     *
     * Fruit automatically de-duplicates install() calls, so they're effectively memoized (within each injector).
     * For example, in this code:
     *
     * fruit::Component<Foo> getFooComponent() {...}
     *
     * fruit::Component<Bar> getBarComponent() {
     *   return fruit::createComponent()
     *       .install(getFooComponent)
     *       .bind<Bar, BarImpl>();
     * }
     *
     * fruit::Component<Baz> getBazComponent() {
     *   return fruit::createComponent()
     *       .install(getFooComponent)
     *       .bind<Baz, BazImpl>();
     * }
     *
     * fruit::Component<Bar, Baz> getBarBazComponent() {
     *   return fruit::createComponent()
     *       .install(getBarComponent)
     *       .install(getBazComponent);
     * }
     *
     * fruit::Injector<Bar, Baz> injector(getBarBazComponent);
     *
     *
     * getFooComponent() will only be called once.
     * For Component functions with arguments, only one call will be done for each set of arguments, but multiple calls
     * might be made if multiple sets of arguments are used.
     *
     * If you actually want a Component function to be called/installed multiple times (e.g. if it binds a multibinding
     * and you actually want multiple multibindings to be bound) you can add a dummy argument and specify different values
     * for that argument when installing the component.
     */
    template <typename... OtherComponentParams, typename... FormalArgs, typename... Args>
    PartialComponent<fruit::impl::InstallComponent<fruit::Component<OtherComponentParams...>(FormalArgs...)>, Bindings...>
    install(fruit::Component<OtherComponentParams...> (*)(FormalArgs...), Args&&... args);
  
    /**
     * Similar to install(), but allows to install a variable number of component functions instead of just 1. This
     * additional flexibility is sometimes useful in templated `get*Component` functions and for other advanced use-cases.
     *
     * To use this method, wrap each get*Component function with its args in a fruit::ComponentFunction<...> object (using
     * the helper function fruit::componentFunction), then pass all the fruit::ComponentFunction<...> objects (which can
     * potentially have different params) to this method.
     *
     * For example:
     *
     * fruit::Component<Foo, Bar> getBarBazComponent() {
     *   return fruit::createComponent()
     *       .installComponentFunctions(
     *           fruit::componentFunction(getFooComponent, a, b, c),
     *           fruit::componentFunction(getBarComponent, x, y));
     * }
     *
     * Is equivalent to:
     *
     * fruit::Component<Foo, Bar> getBarBazComponent() {
     *   return fruit::createComponent()
     *       .install(getFooComponent, a, b, c)
     *       .install(getBarComponent, x, y);
     * }
     * 
     * This is a simple example to show the idea, however in a simple case like this it's easier to just use install().
     */
    template <typename... ComponentFunctions>
    PartialComponent<fruit::impl::InstallComponentFunctions<ComponentFunctions...>, Bindings...>
    installComponentFunctions(ComponentFunctions... componentFunctions);
  
    /**
     * This class is returned by PartialComponent::replace, see the documentation of that method for more information.
     */
    template <typename ReplacedComponent, typename... GetReplacedComponentFormalArgs>
    class PartialComponentWithReplacementInProgress {
    private:
      using storage_t = fruit::impl::PartialComponentStorage<
          fruit::impl::PartialReplaceComponent<ReplacedComponent(GetReplacedComponentFormalArgs...)>, Bindings...>;
  
    public:
      template <typename... FormalArgs, typename... Args>
      PartialComponent<fruit::impl::ReplaceComponent<ReplacedComponent(GetReplacedComponentFormalArgs...),
                                                     ReplacedComponent(FormalArgs...)>,
                       Bindings...>
      with(ReplacedComponent (*)(FormalArgs...), Args&&... args);
  
      PartialComponentWithReplacementInProgress(storage_t storage) // NOLINT(google-explicit-constructor)
         : storage(storage) {}
  
    private:
      storage_t storage;
  
      PartialComponentWithReplacementInProgress() = delete;
    };
  
    /**
     * This allows to replace an installed Component with another one. This is useful for testing.
     * For example, if you have these components:
     *
     * fruit::Component<MyDependency> getDependencyComponent() {...}
     *
     * fruit::Component<Foo> getFooComponent() {
     *     return fruit::createComponent()
     *         .install(getDependencyComponent)
     *         .bind<Foo, FooImpl>();
     * }
     *
     * fruit::Component<Bar> getBarComponent() {
     *     return fruit::createComponent()
     *         .install(getFooComponent)
     *         .bind<Bar, BarImpl>();
     * }
     *
     * When you test Bar, you might want to replace getDependencyComponent with a component that binds a fake
     * MyDependency:
     *
     * fruit::Component<MyDependency> getFakeDependencyComponent() {...}
     *
     * To do so, you can define a component like:
     *
     * fruit::Component<Bar> getBarComponentWithFakeDependency() {
     *     return fruit::createComponent()
     *         .replace(getDependencyComponent).with(getFakeDependencyComponent)
     *         .install(getBarComponent);
     * }
     *
     * This component is equivalent to:
     *
     * fruit::Component<Bar> getBarComponentWithFakeDependency() {
     *     return fruit::createComponent()
     *         .install(getFakeDependencyComponent)
     *         .bind<Foo, FooImpl>()
     *         .bind<Bar, BarImpl>();
     * }
     *
     * However this way you don't need to duplicate the bindings for Foo and Bar, and you don't even need to include them
     * in the translation unit (i.e., cc/cpp file) that defines getBarComponentWithFakeDependency().
     * In codebases with many layers, this can save a lot of duplication.
     *
     * Note that the .replace(...).with(...) must appear *before* installing the component to which it's applied to;
     * e.g., in the example above note how we install getBarComponent after the replacement in
     * getBarComponentWithFakeDependency.
     * If you add a replacement after the replaced component has been installed, Fruit will report an error at run-time.
     *
     * In the example above, the replaced and replacement component functions had no arguments, however it's also possible
     * to replace component functions with args. The arguments of the replaced and replacement component functions are
     * independent; for example .replace(getDependencyComponentWithArgs, 15).with(myFakeComponentWithNoArgs) is allowed
     * and it would replace all install(getDependencyComponentWithArgs, 15) calls with install(myFakeComponentWithNoArgs).
     *
     * The component types returned by the replaced and replacement components must be the same. For example, this is NOT
     * allowed:
     *
     * fruit::Component<MyDependency, SomethingElse> getFakeDependencyComponentWithSomethingElse() {...}
     *
     * fruit::Component<Bar> getBarComponentWithFakeDependency() {
     *     return fruit::createComponent()
     *         .replace(getDependencyComponent).with(getFakeDependencyComponentWithSomethingElse) // error!
     *         .install(getBarComponent);
     * }
     *
     * But replacing a replaced component is allowed:
     *
     * fruit::Component<MyDependency> getOtherFakeDependencyComponent() {...}
     *
     * fruit::Component<Bar> getBarComponentWithOtherFakeDependency() {
     *     return fruit::createComponent()
     *         // The two replacements can appear in any order, but they must both be before the install().
     *         .replace(getFakeDependencyComponent).with(getOtherFakeDependencyComponent)
     *         .replace(getDependencyComponent).with(getFakeDependencyComponent)
     *         .install(getBarComponent);
     * }
     *
     * Of course this is a simple example, in the real world the replacements and the install would probably come from
     * other components.
     *
     * And note that you can also replace components that define replacements, for example:
     *
     * fruit::Component<> getFakeDependencyReplacementComponent() {
     *     return fruit::createComponent()
     *         .replace(getDependencyComponent).with(getFakeDependencyComponentWithSomethingElse);
     * }
     *
     * fruit::Component<...> getComponent() {
     *     return fruit::createComponent()
     *         .replace(getFakeDependencyReplacementComponent).with(...)
     *         .install(...);
     * }
     *
     * Replacements are only installed if the replaced component is installed, otherwise they are ignored.
     * In the first example above, if getFooComponent didn't install getDependencyComponent, when a test creates an
     * injector for getBarComponentWithFakeDependency it would not install getFakeDependencyComponent.
     */
    template <typename... OtherComponentParams, typename... FormalArgs, typename... Args>
    typename PartialComponent<Bindings...>::template PartialComponentWithReplacementInProgress<
        fruit::Component<OtherComponentParams...>, FormalArgs...>
    replace(fruit::Component<OtherComponentParams...> (*)(FormalArgs...), Args&&... args);
  
    ~PartialComponent() = default;
  
    // Do not use. Use fruit::createComponent() instead.
    PartialComponent() = delete;
  
    // Do not use. Only use PartialComponent for temporaries, and then convert it to a Component.
    PartialComponent(const PartialComponent&) = delete;
    PartialComponent(PartialComponent&&) = delete;
  
  private:
    template <typename... OtherBindings>
    friend class PartialComponent;
  
    template <typename... Types>
    friend class Component;
  
    fruit::impl::PartialComponentStorage<Bindings...> storage;
  
    PartialComponent(fruit::impl::PartialComponentStorage<Bindings...> storage); // NOLINT(google-explicit-constructor)
  
    template <typename NewBinding>
    using OpFor = typename fruit::impl::meta::OpForComponent<Bindings...>::template AddBinding<NewBinding>;
  
    friend PartialComponent<> createComponent();
  };
  
  } // namespace fruit
  
  #include <fruit/impl/component.defn.h>
  
  #endif // FRUIT_COMPONENT_H
  