Skip to content

Commit

Permalink
Apply recursion recursively is now possible
Browse files Browse the repository at this point in the history
  • Loading branch information
gracicot committed Sep 1, 2024
1 parent ac62e43 commit 7fd0e16
Show file tree
Hide file tree
Showing 10 changed files with 309 additions and 319 deletions.
183 changes: 41 additions & 142 deletions include/kangaru/detail/cache.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,10 @@
#include "source.hpp"
#include "ctti.hpp"
#include "concepts.hpp"
#include "allocator.hpp"
#include "cache_types.hpp"
#include "source_types.hpp"
#include "heap_storage.hpp"

#include <type_traits>
#include <concepts>
#include <memory>
#include <utility>

#include "define.hpp"
Expand All @@ -25,7 +21,11 @@ namespace kangaru {
struct with_cache {
using source_type = Source;
using cache_type = Cache;


private:
using unwrapped_cache_type = maybe_wrapped_t<cache_type>;

public:
explicit constexpr with_cache(source_type source) noexcept
requires (
std::default_initializable<cache_type>
Expand All @@ -34,88 +34,88 @@ namespace kangaru {
constexpr with_cache(source_type source, cache_type cache) noexcept
: source{std::move(source)}, cache{std::move(cache)} {}

using key_type = typename cache_type::key_type;
using value_type = typename cache_type::value_type;
using mapped_type = typename cache_type::mapped_type;
using iterator = typename cache_type::iterator;
using const_iterator = typename cache_type::const_iterator;
using key_type = typename unwrapped_cache_type::key_type;
using value_type = typename unwrapped_cache_type::value_type;
using mapped_type = typename unwrapped_cache_type::mapped_type;
using iterator = typename unwrapped_cache_type::iterator;
using const_iterator = typename unwrapped_cache_type::const_iterator;

source_type source;

constexpr auto insert(auto&& value) requires requires(cache_type c) { c.insert(KANGARU5_FWD(value)); } {
return cache.insert(KANGARU5_FWD(value));
constexpr auto insert(auto&& value) requires requires(unwrapped_cache_type c) { c.insert(KANGARU5_FWD(value)); } {
return kangaru::maybe_unwrap(cache).insert(KANGARU5_FWD(value));
}

template<typename It>
constexpr auto insert(It begin, It end) requires requires(cache_type c) { c.insert(begin, end); } {
return cache.insert(begin, end);
constexpr auto insert(It begin, It end) requires requires(unwrapped_cache_type c) { c.insert(begin, end); } {
return kangaru::maybe_unwrap(cache).insert(begin, end);
}

[[nodiscard]]
constexpr auto find(auto const& key) requires requires(cache_type c) { c.find(key); } {
return cache.find(key);
constexpr auto find(auto const& key) requires requires(unwrapped_cache_type c) { c.find(key); } {
return kangaru::maybe_unwrap(cache).find(key);
}

[[nodiscard]]
constexpr auto find(auto const& key) const requires requires(cache_type const c) { c.find(key); } {
return cache.find(key);
constexpr auto find(auto const& key) const requires requires(unwrapped_cache_type const c) { c.find(key); } {
return kangaru::maybe_unwrap(cache).find(key);
}

[[nodiscard]]
constexpr auto contains(auto const& key) const requires requires(cache_type c) { c.contains(key); } {
return cache.contains(key);
constexpr auto contains(auto const& key) const requires requires(unwrapped_cache_type c) { c.contains(key); } {
return kangaru::maybe_unwrap(cache).contains(key);
}

[[nodiscard]]
constexpr auto begin() -> typename cache_type::iterator {
return cache.begin();
constexpr auto begin() -> typename unwrapped_cache_type::iterator {
return kangaru::maybe_unwrap(cache).begin();
}

[[nodiscard]]
constexpr auto end() -> typename cache_type::iterator {
return cache.end();
constexpr auto end() -> typename unwrapped_cache_type::iterator {
return kangaru::maybe_unwrap(cache).end();
}

[[nodiscard]]
constexpr auto begin() const {
return cache.begin();
return kangaru::maybe_unwrap(cache).begin();
}

[[nodiscard]]
constexpr auto end() const {
return cache.end();
return kangaru::maybe_unwrap(cache).end();
}

[[nodiscard]]
constexpr auto cbegin() const -> typename cache_type::const_iterator {
return cache.cbegin();
constexpr auto cbegin() const -> typename unwrapped_cache_type::const_iterator {
return kangaru::maybe_unwrap(cache).cbegin();
}

[[nodiscard]]
constexpr auto cend() const -> typename cache_type::const_iterator {
return cache.cend();
constexpr auto cend() const -> typename unwrapped_cache_type::const_iterator {
return kangaru::maybe_unwrap(cache).cend();
}

[[nodiscard]]
constexpr auto empty() const -> bool {
return cache.empty();
return kangaru::maybe_unwrap(cache).empty();
}

constexpr auto clear() -> void {
return cache.clear();
return kangaru::maybe_unwrap(cache).clear();
}

[[nodiscard]]
constexpr auto size() const {
return cache.size();
return kangaru::maybe_unwrap(cache).size();
}

[[nodiscard]]
constexpr auto erase(auto const& key) requires requires(cache_type c) { c.erase(key); } {
return cache.erase(key);
constexpr auto erase(auto const& key) requires requires(unwrapped_cache_type c) { c.erase(key); } {
return kangaru::maybe_unwrap(cache).erase(key);
}

constexpr auto swap(with_cache other) noexcept -> void {
constexpr auto swap(with_cache& other) noexcept -> void {
using std::swap;
swap(source, other.source);
swap(cache, other.cache);
Expand All @@ -126,11 +126,11 @@ namespace kangaru {
requires source_of<detail::utility::forward_like_t<Self, source_type>, T>
friend constexpr auto provide(provide_tag<T> tag, Self&& source) -> T {
constexpr auto id = detail::ctti::type_id_for<T>();
auto const it = source.cache.find(id);
auto const it = kangaru::maybe_unwrap(source.cache).find(id);

if (it == source.cache.end()) {
if (it == kangaru::maybe_unwrap(source.cache).end()) {
auto object = provide(tag, KANGARU5_FWD(source).source);
auto const [it, _] = source.cache.insert(std::pair{id, std::move(object)});
auto const [it, _] = kangaru::maybe_unwrap(source.cache).insert(std::pair{id, std::move(object)});
return static_cast<T>(it->second);
} else {
return static_cast<T>(it->second);
Expand All @@ -147,109 +147,8 @@ namespace kangaru {
}

static_assert(cache_map<with_cache<noop_source>>);

template<source Source, cache_map InnerCache = std::unordered_map<std::size_t, void*>>
struct with_cache_reference_wrapper {
using source_type = source_reference_wrapper_for_t<Source>;
using cache_type = with_cache<Source>;

explicit constexpr with_cache_reference_wrapper(with_cache<Source, InnerCache>& source) noexcept :
source{ref(source.source)}, cache{std::addressof(source)} {}

using key_type = typename cache_type::key_type;
using value_type = typename cache_type::value_type;
using mapped_type = typename cache_type::mapped_type;
using iterator = typename cache_type::iterator;
using const_iterator = typename cache_type::const_iterator;

source_type source;

constexpr auto insert(auto&& value) const requires requires(cache_type c) { c.insert(KANGARU5_FWD(value)); } {
return cache->insert(KANGARU5_FWD(value));
}

template<typename It>
constexpr auto insert(It begin, It end) const requires requires(cache_type c) { c.insert(begin, end); } {
return cache->insert(begin, end);
}

[[nodiscard]]
constexpr auto find(auto const& key) const requires requires(cache_type const c) { c.find(key); } {
return cache->find(key);
}

[[nodiscard]]
constexpr auto contains(auto const& key) const requires requires(cache_type c) { c.contains(key); } {
return cache->contains(key);
}

[[nodiscard]]
constexpr auto begin() const -> typename cache_type::iterator {
return cache->begin();
}

[[nodiscard]]
constexpr auto end() const -> typename cache_type::iterator {
return cache->end();
}

[[nodiscard]]
constexpr auto cbegin() const -> typename cache_type::const_iterator {
return cache->cbegin();
}

[[nodiscard]]
constexpr auto cend() const -> typename cache_type::const_iterator {
return cache->cend();
}

[[nodiscard]]
constexpr auto empty() const -> bool {
return cache->empty();
}

constexpr auto clear() const -> void {
return cache->clear();
}

[[nodiscard]]
constexpr auto size() const {
return cache->size();
}

[[nodiscard]]
constexpr auto erase(auto const& key) const requires requires(cache_type c) { c.erase(key); } {
return cache->erase(key);
}

constexpr auto swap(with_cache_reference_wrapper other) noexcept -> void {
using std::swap;
swap(source, other.source);
swap(cache, other.cache);
}

[[nodiscard]]
constexpr auto unwrap() const -> with_cache<Source, InnerCache>& {
return *cache;
}

private:
template<object T, forwarded<with_cache_reference_wrapper> Self>
requires source_of<detail::utility::forward_like_t<Self, source_type>, T>
friend constexpr auto provide(provide_tag<T> tag, Self&& source) -> T {
return provide(tag, *source.cache);
}

cache_type* cache = {};
};

template<source Source, cache_map Cache>
struct source_reference_wrapper_for<with_cache<Source, Cache>> {
using type = with_cache_reference_wrapper<Source, Cache>;
};

static_assert(cache_map<with_cache_reference_wrapper<with_cache<noop_source>>>);
static_assert(cache_map<with_cache<noop_source, with_cache_reference_wrapper<with_cache<noop_source>>>>);
static_assert(cache_map<source_reference_wrapper<with_cache<with_cache<noop_source>>>>);
static_assert(cache_map<with_cache<noop_source, source_reference_wrapper<with_cache<noop_source>>>>);
}

#include "undef.hpp"
Expand Down
8 changes: 7 additions & 1 deletion include/kangaru/detail/cache_types.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "ctti.hpp"
#include "concepts.hpp"
#include "allocator.hpp"
#include "source_types.hpp"

#include <cstddef>
#include <type_traits>
Expand All @@ -21,7 +22,7 @@

namespace kangaru {
template<typename T>
concept cache_map = requires(T map, detail::ctti::type_id_for_result<T> id) {
concept non_ref_cache_map = requires(T map, detail::ctti::type_id_for_result<T> id) {
{ map.begin() } -> std::forward_iterator;
{ map.end() } -> std::forward_iterator;
{ std::as_const(map).begin() } -> std::forward_iterator;
Expand All @@ -43,6 +44,11 @@ namespace kangaru {
typename T::const_iterator;
};

template<typename T>
concept cache_map = non_ref_cache_map<T> or requires {
requires non_ref_cache_map<source_reference_wrapped_type<T>>;
};

static_assert(cache_map<std::unordered_map<std::size_t, void*>>);

template<cache_map Map>
Expand Down
Loading

0 comments on commit 7fd0e16

Please sign in to comment.