aboutsummaryrefslogtreecommitdiff
path: root/src/DI/factory.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/DI/factory.hpp')
-rw-r--r--src/DI/factory.hpp189
1 files changed, 189 insertions, 0 deletions
diff --git a/src/DI/factory.hpp b/src/DI/factory.hpp
new file mode 100644
index 0000000..13d0eb5
--- /dev/null
+++ b/src/DI/factory.hpp
@@ -0,0 +1,189 @@
+#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 <type_traits>
+#include <utility>
+
+template <class>
+class Factory;
+
+template <class Return>
+// NOLINTNEXTLINE(readability-identifier-naming)
+struct maybe_derive_from_unary_function
+{
+};
+
+template <class Return, class Arg>
+struct maybe_derive_from_unary_function<Return(Arg)>
+ : public std::unary_function<Arg, Return>
+{
+};
+
+template <class Return>
+// NOLINTNEXTLINE(readability-identifier-naming)
+struct maybe_derive_from_binary_function
+{
+};
+
+template <class Return, class ArgOne, class ArgTwo>
+struct maybe_derive_from_binary_function<Return(ArgOne, ArgTwo)>
+ : public std::binary_function<ArgOne, ArgTwo, Return>
+{
+};
+
+template <class Function>
+auto not_null(Function const & /*unused*/) -> bool
+{
+ return true;
+}
+
+template <class Function>
+auto not_null(Function *function_ptr) -> bool
+{
+ return function_ptr;
+}
+
+template <class Return, class Class>
+auto not_null(Return Class::*method_ptr) -> bool
+{
+ return method_ptr;
+}
+
+template <class Function>
+auto not_null(Factory<Function> const &factory) -> bool
+{
+ return !!factory;
+}
+
+template <class Type>
+// NOLINTNEXTLINE(readability-identifier-naming)
+struct uncvref
+{
+ using type =
+ typename std::remove_cv<typename std::remove_reference<Type>::type>::type;
+};
+
+template <class Type>
+// NOLINTNEXTLINE(readability-identifier-naming)
+using uncvref_t = typename uncvref<Type>::type;
+
+template <class Tp, class Up, class = void>
+// NOLINTNEXTLINE(readability-identifier-naming)
+struct is_core_convertible : public std::false_type
+{
+};
+
+template <class Tp, class Up>
+struct is_core_convertible<
+ Tp, Up, decltype(static_cast<void (*)(Up)>(0)(static_cast<Tp (*)()>(0)()))>
+ : public std::true_type
+{
+};
+
+template <class Tp, class Up>
+constexpr bool is_core_convertible_v = is_core_convertible<Tp, Up>::value;
+
+template <typename Function, typename Return, typename... Args>
+concept Callable = !std::is_same_v<uncvref_t<Function>, Factory<Return(Args...)>> &&
+ std::is_invocable_v<Function, Args...> &&
+ is_core_convertible_v<std::invoke_result_t<Function, Args...>, Return>;
+
+template <class Return, class... Args>
+class Factory<Return(Args...)> : public maybe_derive_from_unary_function<Return(Args...)>,
+ public maybe_derive_from_binary_function<Return(Args...)>
+{
+public:
+ using Result = Return;
+
+ Factory() noexcept = default;
+
+ explicit Factory(std::nullptr_t) noexcept {}
+
+ Factory(const Factory &factory);
+
+ Factory(Factory &&factory) noexcept;
+
+ template <class Function>
+ requires Callable<Function, Return, Args...>
+ // 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 <class RhsReturn, class... RhsArgs>
+ auto operator==(const Factory<RhsReturn(RhsArgs...)> &) const -> bool = delete;
+
+ template <class RhsReturn, class... RhsArgs>
+ auto operator!=(const Factory<RhsReturn(RhsArgs...)> &) const -> bool = delete;
+
+ auto operator()(Args... args) const -> Return;
+
+ [[nodiscard]] auto target_type() const noexcept -> const std::type_info &;
+
+ template <typename Tp>
+ auto target() noexcept -> Tp *;
+
+ template <typename Tp>
+ auto target() const noexcept -> const Tp *;
+
+private:
+ using ValFunctor = ValueFunctor<Return(Args...)>;
+
+ ValFunctor _functor;
+};
+
+template <class Return, class... Args>
+Factory(Return (*)(Args...)) -> Factory<Return(Args...)>;
+
+template <class Function,
+ class Stripped = strip_signature_t<decltype(&Function::operator())>>
+Factory(Function) -> Factory<Stripped>;
+
+template <class Return, class... Args>
+inline auto operator==(const Factory<Return(Args...)> &factory, std::nullptr_t) noexcept
+ -> bool
+{
+ return !factory;
+}
+
+template <class Return, class... Args>
+inline auto operator==(std::nullptr_t, const Factory<Return(Args...)> &factory) noexcept
+ -> bool
+{
+ return !factory;
+}
+
+template <class Return, class... Args>
+inline auto operator!=(const Factory<Return(Args...)> &factory, std::nullptr_t) noexcept
+ -> bool
+{
+ return static_cast<bool>(factory);
+}
+
+template <class Return, class... Args>
+inline auto operator!=(std::nullptr_t, const Factory<Return(Args...)> &factory) noexcept
+ -> bool
+{
+ return static_cast<bool>(factory);
+}
+
+#include "factory.tpp"