Skip to content

Commit

Permalink
Changed stateful rebind to be done from inside types instead of from …
Browse files Browse the repository at this point in the history
…outside
  • Loading branch information
gracicot committed Nov 21, 2024
1 parent aff277f commit 7e81ca1
Show file tree
Hide file tree
Showing 5 changed files with 39 additions and 64 deletions.
8 changes: 8 additions & 0 deletions include/kangaru/detail/cache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@ namespace kangaru {
std::ranges::swap(cache, other.cache);
}

template<forwarded<with_cache> Original, forwarded_source NewSource>
static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_cache<std::decay_t<NewSource>, source_reference_wrapper<unwrapped_cache_type>> {
return with_cache<std::decay_t<NewSource>, source_reference_wrapper<unwrapped_cache_type>>{
KANGARU5_FWD(new_source),
KANGARU5_NO_ADL(ref)(original.cache)
};
}

private:
template<typename To>
static constexpr auto cast(detail::cache::adl_castable_to<To> auto&& any) -> To {
Expand Down
8 changes: 8 additions & 0 deletions include/kangaru/detail/heap_storage.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,14 @@ namespace kangaru {
return KANGARU5_NO_ADL(maybe_unwrap)(storage).emplace_from(function);
}

template<forwarded<with_heap_storage> Original, forwarded_source NewSource>
static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_heap_storage<std::decay_t<NewSource>, source_reference_wrapper<maybe_wrapped_t<Storage>>> {
return with_heap_storage<std::decay_t<NewSource>, source_reference_wrapper<maybe_wrapped_t<Storage>>>{
KANGARU5_FWD(new_source),
KANGARU5_NO_ADL(ref)(original.storage)
};
}

private:
template<pointer T> requires source_of<source_type, std::remove_pointer_t<T>>
friend constexpr auto provide(forwarded<with_heap_storage> auto&& source) -> T {
Expand Down
5 changes: 5 additions & 0 deletions include/kangaru/detail/recursive_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,11 @@ namespace kangaru {
}
}

template<forwarded<with_construction> Original, forwarded_source NewSource>
static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_construction<std::decay_t<NewSource>, Construction> {
return with_construction<std::decay_t<NewSource>, Construction>{KANGARU5_FWD(new_source), original.construction};
}

Source source;

private:
Expand Down
74 changes: 10 additions & 64 deletions include/kangaru/detail/source_helper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,45 +20,18 @@ namespace kangaru {
};
};

template<template<typename, typename> typename Branch, kangaru::source Source, typename State>
struct rebind_wrapper<Branch<Source, State>> {
template<kangaru::source NewSource, typename NewState = State> requires requires { typename Branch<NewSource, NewState>; }
struct ttype {
using type = Branch<NewSource, NewState>;
};
};

template<template<typename> typename Branch, kangaru::source Source>
struct rebind_wrapper<Branch<Source> const> {
template<kangaru::source NewSource> requires requires { typename Branch<NewSource>; }
struct ttype {
using type = Branch<NewSource>;
};
};

template<template<typename, typename> typename Branch, kangaru::source Source, typename State>
struct rebind_wrapper<Branch<Source, State> const> {
template<kangaru::source NewSource, typename NewState = State> requires requires { typename Branch<NewSource, NewState>; }
struct ttype {
using type = Branch<NewSource, NewState>;
};
};
} // namespace detail::source_helper

template<typename Source>
concept weak_rebindable_wrapping_source =
concept transparent_rebindable_wrapping_source =
wrapping_source<Source>
and requires {
typename std::type_identity_t<
typename detail::source_helper::rebind_wrapper<Source>::template ttype<
wrapped_source_t<Source>
>::type
>;
};

template<typename Source>
concept stateless_rebindable_wrapping_source =
weak_rebindable_wrapping_source<Source>
and requires(Source source) {
typename std::type_identity_t<
typename detail::source_helper::rebind_wrapper<Source>::template ttype<
Expand All @@ -69,34 +42,24 @@ namespace kangaru {
typename detail::source_helper::rebind_wrapper<Source>::template ttype<std::decay_t<decltype(source.source)>>::type,
std::decay_t<decltype(source.source)>
>;
};;
};

template<typename Source>
concept stateful_rebindable_wrapping_source =
weak_rebindable_wrapping_source<Source>
wrapping_source<Source>
and requires(Source source) {
typename std::type_identity_t<
typename detail::source_helper::rebind_wrapper<Source>::template ttype<
std::decay_t<decltype(source.source)>,
decltype(KANGARU5_NO_ADL(ref)(source))
>::type
>;
requires std::constructible_from<
typename detail::source_helper::rebind_wrapper<Source>::template ttype<
std::decay_t<decltype(source.source)>,
decltype(KANGARU5_NO_ADL(ref)(source))
>::type,
std::decay_t<decltype(source.source)>,
decltype(KANGARU5_NO_ADL(ref)(source))
>;
Source::rebind(source, none_source{});
};

template<typename Source>
concept rebindable_wrapping_source =
stateless_rebindable_wrapping_source<Source>
transparent_rebindable_wrapping_source<Source>
or stateful_rebindable_wrapping_source<Source>;

namespace detail::source_helper {
// TODO: Design an interface where rebinding might branch off in composed sources
// and allow rebinding with a transformed leaf instead of ignoring it.

// Forward declaration because otherwise the top overloads cannot find the bottom ones.
template<kangaru::source Leaf> requires (not reference_wrapper<Leaf> and not rebindable_wrapping_source<Leaf>)
constexpr auto rebind_source_tree(forwarded_source auto&& new_leaf, Leaf&) noexcept;
Expand Down Expand Up @@ -124,15 +87,8 @@ namespace kangaru {
template<rebindable_wrapping_source Wrapper> requires (not reference_wrapper<Wrapper>)
constexpr auto rebind_source_tree(forwarded_source auto&& new_leaf, Wrapper& source) noexcept {
if constexpr (stateful_rebindable_wrapping_source<Wrapper>) {
using rebound = typename detail::source_helper::rebind_wrapper<Wrapper>::template ttype<
decltype(KANGARU5_NO_ADL(rebind_source_tree)(KANGARU5_FWD(new_leaf), source.source)),
decltype(KANGARU5_NO_ADL(ref)(source))
>::type;
return rebound{
KANGARU5_NO_ADL(rebind_source_tree)(KANGARU5_FWD(new_leaf), source.source),
KANGARU5_NO_ADL(ref)(source),
};
} else if constexpr (stateless_rebindable_wrapping_source<Wrapper>) {
return Wrapper::rebind(source, KANGARU5_NO_ADL(rebind_source_tree)(KANGARU5_FWD(new_leaf), source.source));
} else if constexpr (transparent_rebindable_wrapping_source<Wrapper>) {
using rebound = typename detail::source_helper::rebind_wrapper<Wrapper>::template ttype<
decltype(KANGARU5_NO_ADL(rebind_source_tree)(KANGARU5_FWD(new_leaf), source.source))
>::type;
Expand All @@ -143,16 +99,6 @@ namespace kangaru {
static_assert(not std::same_as<Wrapper, Wrapper>, "exhaustive");
}
}

template<typename Source> requires (forwarded_source<Source> and not wrapping_source<std::remove_reference_t<Source>>)
constexpr auto source_tree_leaf(Source&& source) -> auto&& {
return KANGARU5_FWD(source);
}

template<typename Source> requires (wrapping_source<std::remove_reference_t<Source>>)
constexpr auto source_tree_leaf(Source&& source) -> auto&& {
return KANGARU5_NO_ADL(source_tree_leaf)(KANGARU5_FWD(source).source);
}
} // namespace detail::source_helper
} // namespace kangaru

Expand Down
8 changes: 8 additions & 0 deletions include/kangaru/detail/source_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,14 @@ namespace kangaru {
return kangaru::provide<T>(KANGARU5_FWD(source).source);
}

template<forwarded<with_alternative> Original, forwarded_source NewSource>
static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_alternative<std::decay_t<NewSource>, source_reference_wrapper<maybe_wrapped_t<Alternative>>> {
return with_alternative<std::decay_t<NewSource>, source_reference_wrapper<maybe_wrapped_t<Alternative>>>{
KANGARU5_FWD(new_source),
KANGARU5_NO_ADL(ref)(original.alternative)
};
}

private:
Alternative alternative;
};
Expand Down

0 comments on commit 7e81ca1

Please sign in to comment.