diff --git a/include/kangaru/detail/cache.hpp b/include/kangaru/detail/cache.hpp index e578d93..e9f4c3e 100644 --- a/include/kangaru/detail/cache.hpp +++ b/include/kangaru/detail/cache.hpp @@ -131,6 +131,14 @@ namespace kangaru { std::ranges::swap(cache, other.cache); } + template Original, forwarded_source NewSource> + static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_cache, source_reference_wrapper> { + return with_cache, source_reference_wrapper>{ + KANGARU5_FWD(new_source), + KANGARU5_NO_ADL(ref)(original.cache) + }; + } + private: template static constexpr auto cast(detail::cache::adl_castable_to auto&& any) -> To { diff --git a/include/kangaru/detail/heap_storage.hpp b/include/kangaru/detail/heap_storage.hpp index 778682a..14dc0c6 100644 --- a/include/kangaru/detail/heap_storage.hpp +++ b/include/kangaru/detail/heap_storage.hpp @@ -183,6 +183,14 @@ namespace kangaru { return KANGARU5_NO_ADL(maybe_unwrap)(storage).emplace_from(function); } + template Original, forwarded_source NewSource> + static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_heap_storage, source_reference_wrapper>> { + return with_heap_storage, source_reference_wrapper>>{ + KANGARU5_FWD(new_source), + KANGARU5_NO_ADL(ref)(original.storage) + }; + } + private: template requires source_of> friend constexpr auto provide(forwarded auto&& source) -> T { diff --git a/include/kangaru/detail/recursive_source.hpp b/include/kangaru/detail/recursive_source.hpp index ff5040e..ce884b6 100644 --- a/include/kangaru/detail/recursive_source.hpp +++ b/include/kangaru/detail/recursive_source.hpp @@ -235,6 +235,11 @@ namespace kangaru { } } + template Original, forwarded_source NewSource> + static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_construction, Construction> { + return with_construction, Construction>{KANGARU5_FWD(new_source), original.construction}; + } + Source source; private: diff --git a/include/kangaru/detail/source_helper.hpp b/include/kangaru/detail/source_helper.hpp index 431841e..2877d46 100644 --- a/include/kangaru/detail/source_helper.hpp +++ b/include/kangaru/detail/source_helper.hpp @@ -20,14 +20,6 @@ namespace kangaru { }; }; - template typename Branch, kangaru::source Source, typename State> - struct rebind_wrapper> { - template requires requires { typename Branch; } - struct ttype { - using type = Branch; - }; - }; - template typename Branch, kangaru::source Source> struct rebind_wrapper const> { template requires requires { typename Branch; } @@ -35,30 +27,11 @@ namespace kangaru { using type = Branch; }; }; - - template typename Branch, kangaru::source Source, typename State> - struct rebind_wrapper const> { - template requires requires { typename Branch; } - struct ttype { - using type = Branch; - }; - }; } // namespace detail::source_helper template - concept weak_rebindable_wrapping_source = + concept transparent_rebindable_wrapping_source = wrapping_source - and requires { - typename std::type_identity_t< - typename detail::source_helper::rebind_wrapper::template ttype< - wrapped_source_t - >::type - >; - }; - - template - concept stateless_rebindable_wrapping_source = - weak_rebindable_wrapping_source and requires(Source source) { typename std::type_identity_t< typename detail::source_helper::rebind_wrapper::template ttype< @@ -69,34 +42,24 @@ namespace kangaru { typename detail::source_helper::rebind_wrapper::template ttype>::type, std::decay_t >; - };; + }; template concept stateful_rebindable_wrapping_source = - weak_rebindable_wrapping_source + wrapping_source and requires(Source source) { - typename std::type_identity_t< - typename detail::source_helper::rebind_wrapper::template ttype< - std::decay_t, - decltype(KANGARU5_NO_ADL(ref)(source)) - >::type - >; - requires std::constructible_from< - typename detail::source_helper::rebind_wrapper::template ttype< - std::decay_t, - decltype(KANGARU5_NO_ADL(ref)(source)) - >::type, - std::decay_t, - decltype(KANGARU5_NO_ADL(ref)(source)) - >; + Source::rebind(source, none_source{}); }; template concept rebindable_wrapping_source = - stateless_rebindable_wrapping_source + transparent_rebindable_wrapping_source or stateful_rebindable_wrapping_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 requires (not reference_wrapper and not rebindable_wrapping_source) constexpr auto rebind_source_tree(forwarded_source auto&& new_leaf, Leaf&) noexcept; @@ -124,15 +87,8 @@ namespace kangaru { template requires (not reference_wrapper) constexpr auto rebind_source_tree(forwarded_source auto&& new_leaf, Wrapper& source) noexcept { if constexpr (stateful_rebindable_wrapping_source) { - using rebound = typename detail::source_helper::rebind_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) { + return Wrapper::rebind(source, KANGARU5_NO_ADL(rebind_source_tree)(KANGARU5_FWD(new_leaf), source.source)); + } else if constexpr (transparent_rebindable_wrapping_source) { using rebound = typename detail::source_helper::rebind_wrapper::template ttype< decltype(KANGARU5_NO_ADL(rebind_source_tree)(KANGARU5_FWD(new_leaf), source.source)) >::type; @@ -143,16 +99,6 @@ namespace kangaru { static_assert(not std::same_as, "exhaustive"); } } - - template requires (forwarded_source and not wrapping_source>) - constexpr auto source_tree_leaf(Source&& source) -> auto&& { - return KANGARU5_FWD(source); - } - - template requires (wrapping_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 diff --git a/include/kangaru/detail/source_types.hpp b/include/kangaru/detail/source_types.hpp index cde9976..6f03adc 100644 --- a/include/kangaru/detail/source_types.hpp +++ b/include/kangaru/detail/source_types.hpp @@ -250,6 +250,14 @@ namespace kangaru { return kangaru::provide(KANGARU5_FWD(source).source); } + template Original, forwarded_source NewSource> + static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_alternative, source_reference_wrapper>> { + return with_alternative, source_reference_wrapper>>{ + KANGARU5_FWD(new_source), + KANGARU5_NO_ADL(ref)(original.alternative) + }; + } + private: Alternative alternative; };