#pragma once #include "DI/interfaces/copyable_functor.hpp" #include "DI/alloc_functor.hpp" #include "DI/allocation.hpp" #include "DI/copyable_functor.hpp" #include "DI/extra_concepts.hpp" #include "DI/strip_signature.hpp" #include "DI/value_functor.hpp" #include #include template class Factory; template // NOLINTNEXTLINE(readability-identifier-naming) struct maybe_derive_from_unary_function { }; template struct maybe_derive_from_unary_function : public std::unary_function { }; template // NOLINTNEXTLINE(readability-identifier-naming) struct maybe_derive_from_binary_function { }; template struct maybe_derive_from_binary_function : public std::binary_function { }; template auto not_null(Function const & /*unused*/) -> bool { return true; } template auto not_null(Function *function_ptr) -> bool { return function_ptr; } template auto not_null(Return Class::*method_ptr) -> bool { return method_ptr; } template auto not_null(Factory const &factory) -> bool { return !!factory; } template // NOLINTNEXTLINE(readability-identifier-naming) struct uncvref { using type = typename std::remove_cv::type>::type; }; template // NOLINTNEXTLINE(readability-identifier-naming) using uncvref_t = typename uncvref::type; template // NOLINTNEXTLINE(readability-identifier-naming) struct is_core_convertible : public std::false_type { }; template struct is_core_convertible< Tp, Up, decltype(static_cast(0)(static_cast(0)()))> : public std::true_type { }; template constexpr bool is_core_convertible_v = is_core_convertible::value; template concept Callable = !std::is_same_v, Factory> && std::is_invocable_v && is_core_convertible_v, Return>; template class Factory : public maybe_derive_from_unary_function, public maybe_derive_from_binary_function { public: using Result = Return; Factory() noexcept = default; explicit Factory(std::nullptr_t) noexcept {} Factory(const Factory &factory); Factory(Factory &&factory) noexcept; template requires Callable // NOLINTNEXTLINE(google-explicit-constructor) Factory(Function function) : _functor(std::move(function)) { } auto operator=(const Factory &factory) = delete; auto operator=(Factory &&factory) noexcept -> Factory &; auto operator=(std::nullptr_t) noexcept -> Factory &; ~Factory(); explicit operator bool() const noexcept; // deleted overloads close possible hole in the type system template auto operator==(const Factory &) const -> bool = delete; template auto operator!=(const Factory &) const -> bool = delete; auto operator()(Args... args) const -> Return; [[nodiscard]] auto target_type() const noexcept -> const std::type_info &; template auto target() noexcept -> Tp *; template auto target() const noexcept -> const Tp *; private: using ValFunctor = ValueFunctor; ValFunctor _functor; }; template Factory(Return (*)(Args...)) -> Factory; template < class Function, class Stripped = strip_signature_t> Factory(Function) -> Factory; template inline auto operator==(const Factory &factory, std::nullptr_t) noexcept -> bool { return !factory; } template inline auto operator==(std::nullptr_t, const Factory &factory) noexcept -> bool { return !factory; } template inline auto operator!=(const Factory &factory, std::nullptr_t) noexcept -> bool { return static_cast(factory); } template inline auto operator!=(std::nullptr_t, const Factory &factory) noexcept -> bool { return static_cast(factory); } #include "factory.tpp"