Skip to content

Commit 6101be3

Browse files
committed
Rework rebind interface
1 parent b2ab20d commit 6101be3

File tree

12 files changed

+232
-162
lines changed

12 files changed

+232
-162
lines changed

include/kangaru/detail/cache.hpp

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "ctti.hpp"
77
#include "concepts.hpp"
88
#include "cache_types.hpp"
9+
#include "source_helper.hpp"
910

1011
#include <type_traits>
1112
#include <concepts>
@@ -132,10 +133,10 @@ namespace kangaru {
132133
std::ranges::swap(cache, other.cache);
133134
}
134135

135-
template<forwarded<with_cache_asymmetric> Original, forwarded_source NewSource>
136-
static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_cache_asymmetric<std::decay_t<NewSource>, source_reference_wrapper<unwrapped_cache_type>, CacheFrom> {
137-
return with_cache_asymmetric<std::decay_t<NewSource>, source_reference_wrapper<unwrapped_cache_type>, CacheFrom>{
138-
KANGARU5_FWD(new_source),
136+
template<forwarded<with_cache_asymmetric> Original, forwarded_source NewLeaf>
137+
static constexpr auto rebind(Original&& original, NewLeaf&& new_leaf) noexcept -> with_cache_asymmetric<rebind_wrapped_source_result_t<Original, NewLeaf>, source_ref_t<Cache>, CacheFrom> {
138+
return with_cache_asymmetric<rebind_wrapped_source_result_t<Original, NewLeaf>, source_ref_t<Cache>, CacheFrom>{
139+
kangaru::rebind(KANGARU5_FWD(original).source, KANGARU5_FWD(new_leaf)),
139140
KANGARU5_NO_ADL(ref)(original.cache)
140141
};
141142
}
@@ -204,9 +205,13 @@ namespace kangaru {
204205
constexpr with_cache(Source source, Cache cache) noexcept :
205206
parent_t{std::move(source), std::move(cache)} {}
206207

207-
template<forwarded<with_cache> Original, forwarded_source NewSource>
208-
static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_cache<std::decay_t<NewSource>, source_reference_wrapper<maybe_wrapped_t<Cache>>> {
209-
return with_cache<std::decay_t<NewSource>, source_reference_wrapper<maybe_wrapped_t<Cache>>>{parent_t::rebind(static_cast<detail::utility::forward_like_t<Original, parent_t>&&>(original), KANGARU5_FWD(new_source))};
208+
template<forwarded<with_cache> Original, forwarded_source NewLeaf>
209+
static constexpr auto rebind(Original&& original, NewLeaf&& new_leaf) noexcept
210+
-> with_cache<rebind_wrapped_source_result_t<detail::utility::forward_like_t<Original, parent_t>, NewLeaf>, source_ref_t<Cache>>
211+
{
212+
return with_cache<rebind_wrapped_source_result_t<detail::utility::forward_like_t<Original, parent_t>, NewLeaf>, source_ref_t<Cache>>{
213+
parent_t::rebind(static_cast<detail::utility::forward_like_t<Original, parent_t>&&>(original), KANGARU5_FWD(new_leaf))
214+
};
210215
}
211216

212217
template<object T, forwarded<with_cache> Self>
@@ -254,13 +259,6 @@ namespace kangaru {
254259
}
255260
}
256261

257-
template<forwarded<with_cache_using_source> Original, forwarded_source NewSource>
258-
static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_cache_using_source<std::decay_t<NewSource>, SourceFor> {
259-
return with_cache_using_source<std::decay_t<NewSource>, SourceFor>{
260-
KANGARU5_FWD(new_source),
261-
};
262-
}
263-
264262
Source source;
265263
};
266264

include/kangaru/detail/container.hpp

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@
1414

1515
namespace kangaru {
1616
template<injectable T>
17-
using cached_pointer_to_injectable_reference_source = typename cached_pointer_to_source<injectable_reference_source>::template source<T>;
17+
using cached_pointer_to_injectable_reference_source =
18+
typename cached_pointer_to_source<injectable_reference_source>::template source<T>;
1819

19-
template<source Source, cache_map Cache = std::unordered_map<std::size_t, void*>, heap_storage Storage = default_heap_storage>
20+
template<
21+
rebindable_source Source,
22+
cache_map Cache = std::unordered_map<std::size_t, void*>,
23+
heap_storage Storage = default_heap_storage
24+
>
2025
struct container {
2126
explicit constexpr container(Source source) noexcept :
22-
source{
27+
state{
2328
make_source_with_cache(
2429
make_source_with_heap_storage(
2530
make_source_with_exhaustive_construction(
@@ -40,10 +45,10 @@ namespace kangaru {
4045
Storage
4146
>,
4247
Cache
43-
> source;
48+
> state;
4449

4550
template<typename Self, typename S>
46-
static constexpr auto rebound_source_tree(Self&& self, S&& source) {
51+
static constexpr auto container_source(Self&& self, S&& source) {
4752
return with_recursion{
4853
make_source_with_exhaustive_construction(
4954
with_alternative{
@@ -59,22 +64,22 @@ namespace kangaru {
5964
}
6065

6166
template<typename Self>
62-
using rebound_source_tree_t = decltype(
63-
rebound_source_tree(std::declval<Self>(), std::declval<Self>().source)
67+
using container_source_t = decltype(
68+
container_source(std::declval<Self>(), std::declval<Self>().state)
6469
);
6570

6671
public:
6772
template<injectable T>
68-
constexpr auto provide() & -> T requires source_of<rebound_source_tree_t<container&>, T> {
73+
constexpr auto provide() & -> T requires source_of<container_source_t<container&>, T> {
6974
return kangaru::provide<T>(
70-
rebound_source_tree(*this, source)
75+
container_source(*this, state)
7176
);
7277
}
7378

7479
template<injectable T>
75-
constexpr auto provide() && -> T requires source_of<rebound_source_tree_t<container&&>, T> {
80+
constexpr auto provide() && -> T requires source_of<container_source_t<container&&>, T> {
7681
return kangaru::provide<T>(
77-
rebound_source_tree(std::move(*this), std::move(source))
82+
container_source(std::move(*this), std::move(state))
7883
);
7984
}
8085
};

include/kangaru/detail/deducer.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,11 +187,11 @@ namespace kangaru {
187187
if constexpr (source_of<Source, T const&>) {
188188
return kangaru::provide<T const&>(static_cast<Source&&>(*source));
189189
} else if constexpr (source_of<Source, T&>) {
190-
return std::as_const(provide<T&>(static_cast<Source&&>(*source)));
190+
return std::as_const(kangaru::provide<T&>(static_cast<Source&&>(*source)));
191191
} else if constexpr (source_of<Source, T const&&>) {
192-
return static_cast<T const&>(provide<T const&&>(static_cast<Source&&>(*source)));
192+
return static_cast<T const&>(kangaru::provide<T const&&>(static_cast<Source&&>(*source)));
193193
} else if constexpr (source_of<Source, T&&>) {
194-
return static_cast<T const&>(provide<T&&>(static_cast<Source&&>(*source)));
194+
return static_cast<T const&>(kangaru::provide<T&&>(static_cast<Source&&>(*source)));
195195
} else {
196196
static_assert(not std::same_as<T, T>, "exhaustive");
197197
}

include/kangaru/detail/heap_storage.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include "source_types.hpp"
55
#include "source.hpp"
66
#include "allocator.hpp"
7+
#include "source_helper.hpp"
78

89
#include <concepts>
910
#include <vector>
@@ -184,9 +185,9 @@ namespace kangaru {
184185
}
185186

186187
template<forwarded<with_heap_storage> Original, forwarded_source NewSource>
187-
static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_heap_storage<std::decay_t<NewSource>, source_reference_wrapper<maybe_wrapped_t<Storage>>> {
188-
return with_heap_storage<std::decay_t<NewSource>, source_reference_wrapper<maybe_wrapped_t<Storage>>>{
189-
KANGARU5_FWD(new_source),
188+
static constexpr auto rebind(Original&& original, NewSource&& new_leaf) noexcept -> with_heap_storage<rebind_wrapped_source_result_t<Original, NewSource>, source_ref_t<Storage>> {
189+
return with_heap_storage<rebind_wrapped_source_result_t<Original, NewSource>, source_ref_t<Storage>>{
190+
kangaru::rebind(KANGARU5_FWD(original).source, new_leaf),
190191
KANGARU5_NO_ADL(ref)(original.storage)
191192
};
192193
}

include/kangaru/detail/polymorphic_container.hpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,18 @@ namespace kangaru {
2020
struct polymorphic_to_concrete {};
2121

2222
template<injectable T>
23-
struct polymorphic_to_concrete<polymorphic_source<T&>> {
23+
struct polymorphic_to_concrete<kangaru::polymorphic_source<T&>> {
2424
using type = with_polymorphic_cast<with_cast_from<injectable_reference_source<T>, T&>, T&>&;
2525
};
2626

2727
template<kangaru::source T>
2828
using polymorphic_to_concrete_t = typename polymorphic_to_concrete<T>::type;
2929
}
3030

31-
template<source Source, cache_map Cache = polymorphic_map<std::unordered_map<std::size_t, type_erased_source_reference>>, heap_storage Storage = default_heap_storage>
31+
template<rebindable_source Source, cache_map Cache = polymorphic_map<std::unordered_map<std::size_t, type_erased_source_reference>>, heap_storage Storage = default_heap_storage>
3232
struct polymorphic_container {
3333
explicit constexpr polymorphic_container(Source source) noexcept :
34-
source{
34+
state{
3535
make_source_with_cache_asymmetric<detail::polymorphic_container::polymorphic_to_concrete_t>(
3636
make_source_with_dereference(
3737
make_source_with_heap_storage(
@@ -65,10 +65,10 @@ namespace kangaru {
6565
>,
6666
Cache,
6767
detail::polymorphic_container::polymorphic_to_concrete_t
68-
> source;
68+
> state;
6969

7070
template<typename Self, typename S>
71-
static constexpr auto rebound_source_tree(Self&& self, S&& source) {
71+
static constexpr auto container_source(Self&& self, S&& source) {
7272
return with_recursion{
7373
make_source_with_exhaustive_construction(
7474
with_alternative{
@@ -84,22 +84,22 @@ namespace kangaru {
8484
}
8585

8686
template<typename Self>
87-
using rebound_source_tree_t = decltype(
88-
rebound_source_tree(std::declval<Self>(), std::declval<Self>().source)
87+
using container_source_tree_t = decltype(
88+
container_source(std::declval<Self>(), std::declval<Self>().state)
8989
);
9090

9191
public:
9292
template<injectable T>
93-
constexpr auto provide() & -> T requires source_of<rebound_source_tree_t<polymorphic_container&>, T> {
93+
constexpr auto provide() & -> T requires source_of<container_source_tree_t<polymorphic_container&>, T> {
9494
return kangaru::provide<T>(
95-
rebound_source_tree(*this, source)
95+
container_source(*this, state)
9696
);
9797
}
9898

9999
template<injectable T>
100-
constexpr auto provide() && -> T requires source_of<rebound_source_tree_t<polymorphic_container&&>, T> {
100+
constexpr auto provide() && -> T requires source_of<container_source_tree_t<polymorphic_container&&>, T> {
101101
return kangaru::provide<T>(
102-
rebound_source_tree(std::move(*this), std::move(source))
102+
container_source(std::move(*this), std::move(state))
103103
);
104104
}
105105
};

include/kangaru/detail/polymorphic_source.hpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,6 @@ namespace kangaru {
148148
return kangaru::provide<T>(KANGARU5_FWD(source).source);
149149
}
150150

151-
template<forwarded<with_polymorphic_cast> Original, forwarded_source NewSource>
152-
static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_polymorphic_cast<std::decay_t<NewSource>, Primary> {
153-
return with_polymorphic_cast<std::decay_t<NewSource>, Primary>{
154-
KANGARU5_FWD(new_source),
155-
original.cast,
156-
};
157-
}
158-
159151
explicit constexpr operator type_erased_source_reference() noexcept {
160152
return type_erased_source_reference{polymorphic_source<Primary>{source}};
161153
}
@@ -171,9 +163,21 @@ namespace kangaru {
171163
}
172164
};
173165

166+
namespace detail::polymorphic_source {
167+
template<typename>
168+
struct override_polymorphic {};
169+
170+
template<typename... Types>
171+
struct override_polymorphic<std::tuple<Types&...>> {
172+
using type = std::tuple<kangaru::polymorphic_source<Types&>...>;
173+
};
174+
}
175+
174176
// TODO: Check if this is at the right place
175177
template<source Source, injectable Primary>
176-
struct overrides_types_in_cache<with_polymorphic_cast<Source, Primary>> : overrides_types_in_cache<Source> {};
178+
struct overrides_types_in_cache<with_polymorphic_cast<Source, Primary>> :
179+
detail::polymorphic_source::override_polymorphic<overrides_types_in_cache_t<Primary>> {
180+
};
177181
}
178182

179183
#include "undef.hpp"

include/kangaru/detail/recursive_source.hpp

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "injector.hpp"
77
#include "tag.hpp"
88
#include "source.hpp"
9+
#include "source_types.hpp"
910
#include "source_reference_wrapper.hpp"
1011
#include "source_helper.hpp"
1112

@@ -230,13 +231,16 @@ namespace kangaru {
230231
if constexpr (reference_wrapper<Source>) {
231232
return std::as_const(source.construction).template operator()<T>(KANGARU5_FWD(source).source);
232233
} else {
233-
return std::as_const(source.construction).template operator()<T>(kangaru::fwd_ref(KANGARU5_FWD(source).source));
234+
return std::as_const(source.construction).template operator()<T>(KANGARU5_NO_ADL(fwd_ref)(KANGARU5_FWD(source).source));
234235
}
235236
}
236237

237-
template<forwarded<with_construction> Original, forwarded_source NewSource>
238-
static constexpr auto rebind(Original&& original, NewSource&& new_source) -> with_construction<std::decay_t<NewSource>, Construction> {
239-
return with_construction<std::decay_t<NewSource>, Construction>{KANGARU5_FWD(new_source), original.construction};
238+
template<forwarded<with_construction> Original, forwarded_source NewLeaf>
239+
static constexpr auto rebind(Original&& original, NewLeaf&& new_leaf) noexcept -> with_construction<rebind_wrapped_source_result_t<Original, NewLeaf>, Construction> {
240+
return with_construction<rebind_wrapped_source_result_t<Original, NewLeaf>, Construction>{
241+
kangaru::rebind(KANGARU5_FWD(original).source, KANGARU5_FWD(new_leaf)),
242+
original.construction
243+
};
240244
}
241245

242246
Source source;
@@ -284,37 +288,53 @@ namespace kangaru {
284288
// By wrapping source_of in a type, we allow that type to be incomplete!
285289
template<kangaru::source Source, kangaru::injectable T>
286290
struct source_of_sfinae_wrapper : std::bool_constant<source_of<Source, T>> {};
291+
292+
template<kangaru::source Alternative>
293+
struct leaf_as_alternative {
294+
Alternative alternative;
295+
296+
constexpr auto operator()(forwarded_source auto&& leaf) const noexcept {
297+
return KANGARU5_NO_ADL(make_source_with_alternative)(
298+
KANGARU5_NO_ADL(fwd_ref)(KANGARU5_FWD(leaf)),
299+
alternative
300+
);
301+
}
302+
};
287303
}
288304

289-
template<source Source>
305+
template<rebindable_source Source>
290306
struct with_recursion {
291-
private:
292-
static constexpr auto rebound_self(auto&& self) requires wrapping_source<std::remove_reference_t<decltype(self)>> {
293-
auto const source_ref = KANGARU5_NO_ADL(ref)(KANGARU5_NO_ADL(maybe_unwrap)(self.source));
294-
return with_recursion<decltype(source_ref)>{source_ref};
295-
}
296-
297-
template<forwarded<with_recursion> Self>
298-
using rebound_source_t = decltype(
299-
detail::source_helper::rebind_source_tree(
300-
rebound_self(std::declval<Self&>()),
301-
std::declval<Self&>().source
302-
)
303-
);
304-
305-
public:
306-
explicit constexpr with_recursion(Source source) noexcept : source{std::move(source)} {}
307-
308307
Source source;
309308

310309
template<typename T, forwarded<with_recursion> Self> requires (not wrapping_source_of<Self, T>)
311310
constexpr KANGARU5_PROVIDE_FUNCTION_DECL(Self&& source) -> T requires(
312-
detail::recursive_source::source_of_sfinae_wrapper<rebound_source_t<Self>, T>::value
311+
// We uses the sfinae wrapper for source_of
312+
// This forces the compiler to have a third state:
313+
// requires(true) --> goes in
314+
// requires(false) --> tries another function
315+
// requires(<substitution-error>) --> tries another function
316+
//
317+
// The first time the compiler encounter provide, it check source_of
318+
// Then during the evaluation of source_of, it will encounter provide again
319+
// But instead of evaluating source_of, it will see source_of as an incomplete type
320+
// Thus skipping that function and try the next one and detect that one is callable
321+
// The evaluation of source_of will then yeild true, but
322+
// also yield false if it would result in infinite recursion
323+
// Yes, this requires expression will yield different result depending on the metastate of the compiler!
324+
detail::recursive_source::source_of_sfinae_wrapper<
325+
rebind_wrapped_source_result_t<
326+
Self&,
327+
detail::recursive_source::leaf_as_alternative<with_recursion<source_ref_t<wrapped_source_t<Self>>>>
328+
>,
329+
T
330+
>::value
313331
) {
314332
return kangaru::provide<T>(
315-
detail::source_helper::rebind_source_tree(
316-
rebound_self(source),
317-
source.source
333+
kangaru::rebind(
334+
source,
335+
detail::recursive_source::leaf_as_alternative<with_recursion<source_ref_t<wrapped_source_t<Self>>>>{
336+
KANGARU5_NO_ADL(ref)(source.source)
337+
}
318338
)
319339
);
320340
}

include/kangaru/detail/source.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,16 @@ namespace kangaru {
105105
};
106106

107107
template<typename Source> requires weak_wrapping_source<std::remove_reference_t<Source>>
108-
using wrapped_source_t = std::remove_reference_t<decltype(std::declval<Source&&>().source)>;
108+
using wrapped_source_t = std::remove_reference_t<decltype((std::declval<Source&&>().source))>;
109109

110110
template<typename Source>
111111
concept wrapping_source =
112112
weak_wrapping_source<Source>
113113
and source<wrapped_source_t<Source>>;
114114

115+
template<typename Source>
116+
concept forwarded_wrapping_source = wrapping_source<std::remove_reference_t<Source>>;
117+
115118
struct none_source {};
116119
static_assert(source<none_source>);
117120

0 commit comments

Comments
 (0)