Skip to content

Commit

Permalink
Better injectors
Browse files Browse the repository at this point in the history
  • Loading branch information
gracicot committed Aug 6, 2024
1 parent d737997 commit fc3012c
Show file tree
Hide file tree
Showing 4 changed files with 204 additions and 139 deletions.
307 changes: 193 additions & 114 deletions include/kangaru/detail/injector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,75 +12,75 @@

#include "define.hpp"

namespace kangaru::detail::injector {
template<typename Function, typename>
struct parameter_sequence_impl {};

template<typename Function>
requires callable<Function>
struct parameter_sequence_impl<Function, std::index_sequence<>> {
using type = std::index_sequence<>;
};

template<typename Function, std::size_t head, std::size_t... tail>
requires callable<Function, kangaru::placeholder_deducer, detail::utility::expand<kangaru::placeholder_deducer, tail>...>
struct parameter_sequence_impl<Function, std::index_sequence<head, tail...>> {
using type = std::index_sequence<head, tail...>;
};

template<typename Function, std::size_t head, std::size_t... tail>
struct parameter_sequence_impl<Function, std::index_sequence<head, tail...>> :
parameter_sequence_impl<Function, std::index_sequence<(tail - 1)...>> {};

template<typename F, std::size_t max>
using parameter_sequence = parameter_sequence_impl<F, std::make_index_sequence<max>>;

template<typename F, std::size_t max>
using parameter_sequence_t = typename parameter_sequence<F, max>::type;

template<typename F, typename Deducer, typename S>
concept invocable_with_strict_deducer_sequence = requires(F&& function, Deducer deduce, S seq) {
detail::deducer::invoke_with_strict_deducer_sequence(seq, KANGARU5_FWD(function), deduce);
};

template<typename F, typename Deducer, typename S>
concept invocable_with_deducer_sequence = requires(F&& function, Deducer deduce, S seq) {
detail::deducer::invoke_with_deducer_sequence(seq, KANGARU5_FWD(function), deduce);
};

template<template<typename Deducer, std::size_t nth> typename Expand, typename Function, typename Deducer, typename, typename = std::index_sequence<>>
struct injectable_sequence {};

template<template<typename Deducer, std::size_t nth> typename Expand, typename Function, typename Deducer, std::size_t... drop>
requires callable<Function, Expand<kangaru::placeholder_deducer, drop>...>
struct injectable_sequence<Expand, Function, Deducer, std::index_sequence<>, std::index_sequence<drop...>> {
using type = std::index_sequence<>;
};

template<template<typename Deducer, std::size_t nth> typename Expand, typename Function, typename Deducer, std::size_t head, std::size_t... tail, std::size_t... drop>
requires callable<Function, Deducer, Expand<Deducer, tail>..., detail::utility::expand<kangaru::placeholder_deducer, drop>...>
struct injectable_sequence<Expand, Function, Deducer, std::index_sequence<head, tail...>, std::index_sequence<drop...>> {
using type = std::index_sequence<head, tail...>;
};

template<template<typename Deducer, std::size_t nth> typename Expand, typename Function, typename Deducer, std::size_t head, std::size_t... tail, std::size_t... drop>
struct injectable_sequence<Expand, Function, Deducer, std::index_sequence<head, tail...>, std::index_sequence<drop...>> :
injectable_sequence<Expand, Function, Deducer, std::index_sequence<(tail - 1)...>, std::index_sequence<drop..., sizeof...(drop)>> {};

template<typename Function, typename Deducer, std::size_t max>
using spread_sequence_t = typename injectable_sequence<detail::utility::expand, Function, Deducer, parameter_sequence_t<Function, max>>::type;

template<typename Function, std::size_t max>
struct make_strict_expander {
template<typename Deducer, std::size_t nth>
using ttype = detail::deducer::filtered_value_category_deducer_for<Function, Deducer, nth, max>;
};

template<typename Function, typename Deducer, std::size_t max>
using strict_spread_sequence_t = typename injectable_sequence<make_strict_expander<Function, max>::template ttype, Function, Deducer, parameter_sequence_t<Function, max>>::type;
}

namespace kangaru {
namespace detail::injector {
template<typename Function, typename>
struct parameter_sequence_impl {};

template<typename Function>
requires callable<Function>
struct parameter_sequence_impl<Function, std::index_sequence<>> {
using type = std::index_sequence<>;
};

template<typename Function, std::size_t head, std::size_t... tail>
requires callable<Function, kangaru::placeholder_deducer, detail::utility::expand<kangaru::placeholder_deducer, tail>...>
struct parameter_sequence_impl<Function, std::index_sequence<head, tail...>> {
using type = std::index_sequence<head, tail...>;
};

template<typename Function, std::size_t head, std::size_t... tail>
struct parameter_sequence_impl<Function, std::index_sequence<head, tail...>> :
parameter_sequence_impl<Function, std::index_sequence<(tail - 1)...>> {};

template<typename F, std::size_t max>
using parameter_sequence = parameter_sequence_impl<F, std::make_index_sequence<max>>;

template<typename F, std::size_t max>
using parameter_sequence_t = typename parameter_sequence<F, max>::type;

template<typename F, typename Deducer, typename S>
concept invocable_with_strict_deducer_sequence = requires(F&& function, Deducer deduce, S seq) {
detail::deducer::invoke_with_strict_deducer_sequence(seq, KANGARU5_FWD(function), deduce);
};

template<typename F, typename Deducer, typename S>
concept invocable_with_deducer_sequence = requires(F&& function, Deducer deduce, S seq) {
detail::deducer::invoke_with_deducer_sequence(seq, KANGARU5_FWD(function), deduce);
};

template<template<typename Deducer, std::size_t nth> typename Expand, typename Function, typename Deducer, typename, typename = std::index_sequence<>>
struct injectable_sequence {};

template<template<typename Deducer, std::size_t nth> typename Expand, typename Function, typename Deducer, std::size_t... drop>
requires callable<Function, Expand<kangaru::placeholder_deducer, drop>...>
struct injectable_sequence<Expand, Function, Deducer, std::index_sequence<>, std::index_sequence<drop...>> {
using type = std::index_sequence<>;
};

template<template<typename Deducer, std::size_t nth> typename Expand, typename Function, typename Deducer, std::size_t head, std::size_t... tail, std::size_t... drop>
requires callable<Function, Deducer, Expand<Deducer, tail>..., detail::utility::expand<kangaru::placeholder_deducer, drop>...>
struct injectable_sequence<Expand, Function, Deducer, std::index_sequence<head, tail...>, std::index_sequence<drop...>> {
using type = std::index_sequence<head, tail...>;
};

template<template<typename Deducer, std::size_t nth> typename Expand, typename Function, typename Deducer, std::size_t head, std::size_t... tail, std::size_t... drop>
struct injectable_sequence<Expand, Function, Deducer, std::index_sequence<head, tail...>, std::index_sequence<drop...>> :
injectable_sequence<Expand, Function, Deducer, std::index_sequence<(tail - 1)...>, std::index_sequence<drop..., sizeof...(drop)>> {};

template<typename Function, typename Deducer, std::size_t max>
using spread_sequence_t = typename injectable_sequence<detail::utility::expand, Function, Deducer, parameter_sequence_t<Function, max>>::type;

template<typename Function, std::size_t max>
struct make_strict_expander {
template<typename Deducer, std::size_t nth>
using ttype = detail::deducer::filtered_value_category_deducer_for<Function, Deducer, nth, max>;
};

template<typename Function, typename Deducer, std::size_t max>
using strict_spread_sequence_t = typename injectable_sequence<make_strict_expander<Function, max>::template ttype, Function, Deducer, parameter_sequence_t<Function, max>>::type;
} // namespace detail::injector

template<typename T>
concept injector = object<T> and std::move_constructible<T>;

Expand All @@ -89,30 +89,67 @@ namespace kangaru {
requires detail::injector::parameter_sequence_impl<F, std::make_index_sequence<max>>::type;
};

template<source Source>
struct simple_injector {
explicit constexpr simple_injector(Source source) noexcept : source{std::move(source)} {}
template<source Source, std::size_t N>
struct fixed_injector {
explicit constexpr fixed_injector(Source source) noexcept : source{std::move(source)} {}

constexpr auto operator()(auto&& function) & -> decltype(auto) requires callable<decltype(function), basic_deducer<Source&>> {
return kangaru::invoke_with_deducers(KANGARU5_FWD(function), basic_deducer<Source&>{source});
constexpr auto operator()(auto&& function) & -> decltype(auto)
requires detail::injector::invocable_with_deducer_sequence<decltype(function), basic_deducer<Source&>, std::make_index_sequence<N>>
{
return expand_deducers(std::make_index_sequence<N>{}, KANGARU5_FWD(function), source);
}

constexpr auto operator()(callable<basic_deducer<Source const&>> auto&& function) const& -> decltype(auto) requires callable<decltype(function), basic_deducer<Source const&>> {
return kangaru::invoke_with_deducers(KANGARU5_FWD(function), basic_deducer<Source const&>{source});
constexpr auto operator()(callable<basic_deducer<Source const&>> auto&& function) const& -> decltype(auto)
requires detail::injector::invocable_with_deducer_sequence<decltype(function), basic_deducer<Source const&>, std::make_index_sequence<N>>
{
return expand_deducers(std::make_index_sequence<N>{}, KANGARU5_FWD(function), source);
}

constexpr auto operator()(callable<basic_deducer<Source&&>> auto&& function) && -> decltype(auto) {
return kangaru::invoke_with_deducers(KANGARU5_FWD(function), basic_deducer<Source&&>{std::move(source)});
constexpr auto operator()(callable<basic_deducer<Source&&>> auto&& function) && -> decltype(auto)
requires detail::injector::invocable_with_deducer_sequence<decltype(function), basic_deducer<Source&&>, std::make_index_sequence<N>>
{
return expand_deducers(std::make_index_sequence<N>{}, KANGARU5_FWD(function), std::move(source));
}

constexpr auto operator()(callable<basic_deducer<Source const&&>> auto&& function) const&& -> decltype(auto) {
return kangaru::invoke_with_deducers(KANGARU5_FWD(function), basic_deducer<Source const&&>{std::move(source)});
constexpr auto operator()(callable<basic_deducer<Source const&&>> auto&& function) const&& -> decltype(auto)
requires detail::injector::invocable_with_deducer_sequence<decltype(function), basic_deducer<Source const&&>, std::make_index_sequence<N>>
{
return expand_deducers(std::make_index_sequence<N>{}, KANGARU5_FWD(function), std::move(source));
}

private:
template<std::size_t... s>
static constexpr auto expand_deducers(std::index_sequence<s...>, auto&& function, auto&& source) -> decltype(auto) {
using Deducer = basic_deducer<decltype(source)>;
return kangaru::invoke_with_deducers(KANGARU5_FWD(function), (void(s), Deducer{KANGARU5_FWD(source)})...);
}

Source source;
};

template<source Source>
using simple_injector = fixed_injector<Source, 1>;

struct make_simple_injector_function {
template<typename Source> requires kangaru::source<std::remove_cvref_t<Source>>
inline constexpr auto operator()(Source&& source) const {
return simple_injector<std::remove_cvref_t<Source>>{KANGARU5_FWD(source)};
}
};

inline constexpr auto make_simple_injector = make_simple_injector_function{};

template<std::size_t N>
struct make_fixed_injector_function {
template<typename Source> requires kangaru::source<std::remove_cvref_t<Source>>
inline constexpr auto operator()(Source&& source) const {
return fixed_injector<std::remove_cvref_t<Source>, N>{KANGARU5_FWD(source)};
}
};

template<std::size_t N>
inline constexpr auto make_fixed_injector = make_fixed_injector_function<N>{};

template<source Source, std::size_t max>
struct basic_spread_injector {
explicit constexpr basic_spread_injector(Source source) noexcept : source{std::move(source)} {}
Expand Down Expand Up @@ -147,6 +184,51 @@ namespace kangaru {
Source source;
};

template<source Source>
using fast_spread_injector = basic_spread_injector<Source, 4>;

template<source Source>
using spread_injector = basic_spread_injector<Source, 8>;

template<source Source>
using slow_spread_injector = basic_spread_injector<Source, 16>;

template<source Source>
using optional_injector = basic_spread_injector<Source, 1>;

struct make_fast_spread_injector_function {
template<typename Source> requires kangaru::source<std::remove_cvref_t<Source>>
inline constexpr auto operator()(Source&& source) const {
return fast_spread_injector<std::remove_cvref_t<Source>>{KANGARU5_FWD(source)};
}
};

struct make_spread_injector_function {
template<typename Source> requires kangaru::source<std::remove_cvref_t<Source>>
inline constexpr auto operator()(Source&& source) const {
return spread_injector<std::remove_cvref_t<Source>>{KANGARU5_FWD(source)};
}
};

struct make_slow_spread_injector_function {
template<typename Source> requires kangaru::source<std::remove_cvref_t<Source>>
inline constexpr auto operator()(Source&& source) const {
return slow_spread_injector<std::remove_cvref_t<Source>>{KANGARU5_FWD(source)};
}
};

struct make_optional_injector_function {
template<typename Source> requires kangaru::source<std::remove_cvref_t<Source>>
inline constexpr auto operator()(Source&& source) const {
return optional_injector<std::remove_cvref_t<Source>>{KANGARU5_FWD(source)};
}
};

inline constexpr auto make_fast_spread_injector = make_fast_spread_injector_function{};
inline constexpr auto make_spread_injector = make_spread_injector_function{};
inline constexpr auto make_slow_spread_injector = make_slow_spread_injector_function{};
inline constexpr auto make_optional_injector = make_optional_injector_function{};

template<source Source, std::size_t max>
struct basic_strict_spread_injector {
explicit constexpr basic_strict_spread_injector(Source source) noexcept : source{std::move(source)} {}
Expand Down Expand Up @@ -181,15 +263,6 @@ namespace kangaru {
Source source;
};

template<source Source>
using fast_spread_injector = basic_spread_injector<Source, 4>;

template<source Source>
using spread_injector = basic_spread_injector<Source, 8>;

template<source Source>
using slow_spread_injector = basic_spread_injector<Source, 16>;

template<source Source>
using strict_fast_spread_injector = basic_strict_spread_injector<Source, 4>;

Expand All @@ -199,35 +272,41 @@ namespace kangaru {
template<source Source>
using strict_slow_spread_injector = basic_strict_spread_injector<Source, 16>;

template<typename Source> requires source<std::decay_t<Source>>
inline constexpr auto make_fast_spread_injector(Source&& source) {
return fast_spread_injector<std::decay_t<Source>>{KANGARU5_FWD(source)};
}
template<source Source>
using strict_optional_injector = basic_strict_spread_injector<Source, 1>;

template<typename Source> requires source<std::decay_t<Source>>
inline constexpr auto make_spread_injector(Source&& source) {
return spread_injector<std::decay_t<Source>>{KANGARU5_FWD(source)};
}
struct make_strict_fast_spread_injector_function {
template<typename Source> requires kangaru::source<std::remove_cvref_t<Source>>
inline constexpr auto operator()(Source&& source) const {
return strict_fast_spread_injector<std::remove_cvref_t<Source>>{KANGARU5_FWD(source)};
}
};

template<typename Source> requires source<std::decay_t<Source>>
inline constexpr auto make_slow_spread_injector(Source&& source) {
return slow_spread_injector<std::decay_t<Source>>{KANGARU5_FWD(source)};
}

template<typename Source> requires source<std::decay_t<Source>>
inline constexpr auto make_strict_fast_spread_injector(Source&& source) {
return strict_fast_spread_injector<std::decay_t<Source>>{KANGARU5_FWD(source)};
}
struct make_strict_spread_injector_function {
template<typename Source> requires kangaru::source<std::remove_cvref_t<Source>>
inline constexpr auto operator()(Source&& source) const {
return strict_spread_injector<std::remove_cvref_t<Source>>{KANGARU5_FWD(source)};
}
};

template<typename Source> requires source<std::decay_t<Source>>
inline constexpr auto make_strict_spread_injector(Source&& source) {
return strict_spread_injector<std::decay_t<Source>>{KANGARU5_FWD(source)};
}
struct make_strict_slow_spread_injector_function {
template<typename Source> requires kangaru::source<std::remove_cvref_t<Source>>
inline constexpr auto operator()(Source&& source) const {
return strict_slow_spread_injector<std::remove_cvref_t<Source>>{KANGARU5_FWD(source)};
}
};

template<typename Source> requires source<std::decay_t<Source>>
inline constexpr auto make_strict_slow_spread_injector(Source&& source) {
return strict_slow_spread_injector<std::decay_t<Source>>{KANGARU5_FWD(source)};
}
struct make_strict_optional_injector_function {
template<typename Source> requires kangaru::source<std::remove_cvref_t<Source>>
inline constexpr auto operator()(Source&& source) const {
return strict_optional_injector<std::remove_cvref_t<Source>>{KANGARU5_FWD(source)};
}
};

inline constexpr auto make_strict_spread_injector = make_strict_spread_injector_function{};
inline constexpr auto make_stict_slow_spread_injector = make_strict_slow_spread_injector_function{};
inline constexpr auto make_strict_fast_spread_injector = make_strict_fast_spread_injector_function{};
inline constexpr auto make_strict_optional_injector = make_strict_optional_injector_function{};

template<injector Injector1, injector Injector2>
struct composed_injector {
Expand Down Expand Up @@ -278,7 +357,7 @@ namespace kangaru {
template<typename... Args>
auto operator()(Args...) -> decltype(std::declval<F>()(std::declval<DeduceFirst>()..., std::declval<Args>()...));
};

Injector1 injector1;
Injector2 injector2;
};
Expand Down
14 changes: 0 additions & 14 deletions include/kangaru/detail/recursive_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,6 @@
#include "define.hpp"

namespace kangaru {
struct make_spread_injector_function {
template<typename Source> requires source<std::remove_cvref_t<Source>>
constexpr auto operator()(Source&& source) const noexcept {
return make_spread_injector(KANGARU5_FWD(source));
}
};

struct make_strict_spread_injector_function {
template<typename Source> requires source<std::remove_cvref_t<Source>>
constexpr auto operator()(Source&& source) const noexcept {
return make_strict_spread_injector(KANGARU5_FWD(source));
}
};

template<typename T>
concept construction = movable_object<T> and requires {
detail::utility::template_type_identity<T::template construct>{};
Expand Down
Loading

0 comments on commit fc3012c

Please sign in to comment.