Skip to content

Commit a05a261

Browse files
committed
Added many source types useful for polymorphism and abstract classes, implemented a draft for lazy initialization in modular sources
1 parent a2a53b8 commit a05a261

File tree

2 files changed

+519
-79
lines changed

2 files changed

+519
-79
lines changed

include/kangaru/detail/source_types.hpp

Lines changed: 179 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,32 @@
1919

2020
#include "define.hpp"
2121

22+
namespace kangaru::detail::source_types {
23+
struct from_tuple_t { using is_deducer = kangaru_deducer_tag; } inline constexpr from_tuple{};
24+
}
25+
2226
namespace kangaru {
27+
template<>
28+
struct allow_injection_using<detail::source_types::from_tuple_t> : std::false_type {};
29+
30+
template<source... Sources>
31+
struct composed_source;
32+
33+
template<source... SourcesLhs, source... SourcesRhs>
34+
auto composed_source_cat(composed_source<SourcesLhs...> const& lhs, composed_source<SourcesRhs...> const& rhs) -> composed_source<SourcesLhs..., SourcesRhs...>;
35+
36+
template<source... SourcesLhs, source... SourcesRhs>
37+
auto composed_source_cat(composed_source<SourcesLhs...> const& lhs, composed_source<SourcesRhs...>&& rhs) -> composed_source<SourcesLhs..., SourcesRhs...>;
38+
39+
template<source... SourcesLhs, source... SourcesRhs>
40+
auto composed_source_cat(composed_source<SourcesLhs...>&& lhs, composed_source<SourcesRhs...> const& rhs) -> composed_source<SourcesLhs..., SourcesRhs...>;
41+
42+
template<source... SourcesLhs, source... SourcesRhs>
43+
auto composed_source_cat(composed_source<SourcesLhs...>&& lhs, composed_source<SourcesRhs...>&& rhs) -> composed_source<SourcesLhs..., SourcesRhs...>;
44+
2345
KANGARU5_EXPORT template<source... Sources>
2446
struct composed_source {
25-
explicit constexpr composed_source(Sources... sources) noexcept : sources{std::move(sources)...} {}
47+
explicit(sizeof...(Sources) == 1) constexpr composed_source(Sources... sources) noexcept : sources{std::move(sources)...} {}
2648

2749
template<injectable T>
2850
constexpr KANGARU5_PROVIDE_FUNCTION_FRIEND auto provide(KANGARU5_PROVIDE_FUNCTION_THIS forwarded<composed_source> auto&& source) -> T
@@ -39,7 +61,21 @@ namespace kangaru {
3961
((source_of<detail::utility::forward_like_t<decltype(source), Sources>, T> ? 1 : 0) + ... + 0) > 1
4062
) = delete;
4163

64+
template<source... SourcesLhs, source... SourcesRhs>
65+
friend auto composed_source_cat(composed_source<SourcesLhs...> const& lhs, composed_source<SourcesRhs...> const& rhs) -> composed_source<SourcesLhs..., SourcesRhs...>;
66+
67+
template<source... SourcesLhs, source... SourcesRhs>
68+
friend auto composed_source_cat(composed_source<SourcesLhs...> const& lhs, composed_source<SourcesRhs...>&& rhs) -> composed_source<SourcesLhs..., SourcesRhs...>;
69+
70+
template<source... SourcesLhs, source... SourcesRhs>
71+
friend auto composed_source_cat(composed_source<SourcesLhs...>&& lhs, composed_source<SourcesRhs...> const& rhs) -> composed_source<SourcesLhs..., SourcesRhs...>;
72+
73+
template<source... SourcesLhs, source... SourcesRhs>
74+
friend auto composed_source_cat(composed_source<SourcesLhs...>&& lhs, composed_source<SourcesRhs...>&& rhs) -> composed_source<SourcesLhs..., SourcesRhs...>;
75+
4276
private:
77+
explicit constexpr composed_source(detail::source_types::from_tuple_t, std::tuple<Sources...>&& sources) noexcept : sources{std::move(sources)} {}
78+
4379
template<typename T, typename Self, std::size_t... S> requires(sizeof...(Sources) > 0)
4480
consteval static auto index_of(std::index_sequence<S...>) {
4581
return ((source_of<detail::utility::forward_like_t<Self, Sources>, T> ? S : 0) + ...);
@@ -48,6 +84,29 @@ namespace kangaru {
4884
std::tuple<Sources...> sources;
4985
};
5086

87+
template<source... SourcesLhs, source... SourcesRhs>
88+
auto composed_source_cat(composed_source<SourcesLhs...> const& lhs, composed_source<SourcesRhs...> const& rhs) -> composed_source<SourcesLhs..., SourcesRhs...> {
89+
return composed_source<SourcesLhs..., SourcesRhs...>{detail::source_types::from_tuple, std::tuple_cat(lhs.sources, rhs.sources)};
90+
}
91+
92+
template<source... SourcesLhs, source... SourcesRhs>
93+
auto composed_source_cat(composed_source<SourcesLhs...> const& lhs, composed_source<SourcesRhs...>&& rhs) -> composed_source<SourcesLhs..., SourcesRhs...> {
94+
return composed_source<SourcesLhs..., SourcesRhs...>{detail::source_types::from_tuple, std::tuple_cat(lhs.sources, std::move(rhs).sources)};
95+
}
96+
97+
template<source... SourcesLhs, source... SourcesRhs>
98+
auto composed_source_cat(composed_source<SourcesLhs...>&& lhs, composed_source<SourcesRhs...> const& rhs) -> composed_source<SourcesLhs..., SourcesRhs...> {
99+
return composed_source<SourcesLhs..., SourcesRhs...>{detail::source_types::from_tuple, std::tuple_cat(std::move(lhs).sources, rhs.sources)};
100+
}
101+
102+
template<source... SourcesLhs, source... SourcesRhs>
103+
auto composed_source_cat(composed_source<SourcesLhs...>&& lhs, composed_source<SourcesRhs...>&& rhs) -> composed_source<SourcesLhs..., SourcesRhs...> {
104+
return composed_source<SourcesLhs..., SourcesRhs...>{detail::source_types::from_tuple, std::tuple_cat(std::move(lhs).sources, std::move(rhs).sources)};
105+
}
106+
107+
template<source Lhs, source Rhs>
108+
using composed_source_cat_t = decltype(KANGARU5_NO_ADL(composed_source_cat)(std::declval<Lhs>(), std::declval<Rhs>()));
109+
51110
KANGARU5_EXPORT inline constexpr auto compose(forwarded_source auto&&... sources) {
52111
return composed_source<std::decay_t<decltype(sources)>...>{KANGARU5_FWD(sources)...};
53112
}
@@ -179,15 +238,37 @@ namespace kangaru {
179238
reference_source(T&&) -> reference_source<std::decay_t<T>>;
180239

181240
KANGARU5_EXPORT template<object T>
182-
struct external_rvalue_source {
183-
explicit constexpr external_rvalue_source(T&& reference) noexcept : reference{std::addressof(reference)} {}
241+
struct shared_pointer_source {
242+
template<typename From = T> requires(not deducer<std::remove_cvref_t<From>> and std::convertible_to<From&&, T>)
243+
explicit constexpr shared_pointer_source(From&& object) noexcept :
244+
object{
245+
std::make_shared<T>(
246+
KANGARU5_FWD(object)
247+
)
248+
} {}
184249

185-
constexpr auto provide() const& -> T&& {
186-
return std::move(*reference);
250+
template<typename... Args> requires constructor_callable<T, Args...>
251+
constexpr shared_pointer_source(Args... args) :
252+
object{
253+
std::make_shared<T>(
254+
KANGARU5_NO_ADL(make_in_place<T>)(KANGARU5_FWD(args)...)
255+
)
256+
} {}
257+
258+
constexpr auto provide() const& -> std::shared_ptr<T> {
259+
return object;
260+
}
261+
262+
// TODO: Should we move the shared pointer?
263+
constexpr auto provide() && -> std::shared_ptr<T> {
264+
return object;
187265
}
188266

189267
private:
190-
T* reference;
268+
std::shared_ptr<T> object;
269+
270+
template<kangaru::object U>
271+
friend auto attribute(allow_empty_injection<shared_pointer_source<U>>) -> std::true_type;
191272
};
192273

193274
KANGARU5_EXPORT template<object T>
@@ -202,6 +283,98 @@ namespace kangaru {
202283
T* reference;
203284
};
204285

286+
KANGARU5_EXPORT template<object T>
287+
struct external_rvalue_source {
288+
explicit constexpr external_rvalue_source(T&& reference) noexcept : reference{std::addressof(reference)} {}
289+
290+
constexpr auto provide() const& -> T&& {
291+
return std::move(*reference);
292+
}
293+
294+
private:
295+
T* reference;
296+
};
297+
298+
KANGARU5_EXPORT template<object Base, std::derived_from<Base> T>
299+
struct derived_reference_source {
300+
template<typename From = T> requires(not deducer<std::remove_cvref_t<From>> and std::convertible_to<From&&, T>)
301+
explicit constexpr derived_reference_source(From&& object) noexcept : object(KANGARU5_FWD(object)) {}
302+
303+
template<typename... Args> requires constructor_callable<T, Args...>
304+
constexpr derived_reference_source(Args... args) : object(KANGARU5_NO_ADL(constructor<T>)(KANGARU5_FWD(args)...)) {}
305+
306+
constexpr auto provide() & -> Base& {
307+
return object;
308+
}
309+
310+
constexpr auto provide() && -> Base& {
311+
return object;
312+
}
313+
314+
private:
315+
T object;
316+
317+
template<kangaru::object B, std::derived_from<B> U>
318+
friend auto attribute(allow_empty_injection<derived_reference_source<B, U>>) -> std::true_type;
319+
};
320+
321+
KANGARU5_EXPORT template<object Base, std::derived_from<Base> T>
322+
struct derived_pointer_source {
323+
template<typename From = T> requires(not deducer<std::remove_cvref_t<From>> and std::convertible_to<From&&, T>)
324+
explicit constexpr derived_pointer_source(From&& object) noexcept : object(KANGARU5_FWD(object)) {}
325+
326+
template<typename... Args> requires constructor_callable<T, Args...>
327+
constexpr derived_pointer_source(Args... args) : object(KANGARU5_NO_ADL(constructor<T>)(KANGARU5_FWD(args)...)) {}
328+
329+
constexpr auto provide() & -> Base* {
330+
return object;
331+
}
332+
333+
constexpr auto provide() && -> Base* {
334+
return object;
335+
}
336+
337+
private:
338+
T object;
339+
340+
template<kangaru::object B, std::derived_from<B> U>
341+
friend auto attribute(allow_empty_injection<derived_pointer_source<B, U>>) -> std::true_type;
342+
};
343+
344+
KANGARU5_EXPORT template<object Base, std::derived_from<Base> T>
345+
struct derived_shared_pointer_source {
346+
template<typename From = T> requires(not deducer<std::remove_cvref_t<From>> and std::convertible_to<From&&, T>)
347+
explicit constexpr derived_shared_pointer_source(From&& object) noexcept :
348+
object{
349+
std::make_shared<T>(
350+
KANGARU5_FWD(object)
351+
)
352+
} {}
353+
354+
template<typename... Args> requires constructor_callable<T, Args...>
355+
constexpr derived_shared_pointer_source(Args... args) :
356+
object{
357+
std::make_shared<T>(
358+
KANGARU5_NO_ADL(make_in_place<T>)(KANGARU5_FWD(args)...)
359+
)
360+
} {}
361+
362+
constexpr auto provide() const& -> std::shared_ptr<Base> {
363+
return object;
364+
}
365+
366+
// TODO: Should we move the shared pointer?
367+
constexpr auto provide() && -> std::shared_ptr<Base> {
368+
return object;
369+
}
370+
371+
private:
372+
std::shared_ptr<T> object;
373+
374+
template<kangaru::object B, std::derived_from<B> U>
375+
friend auto attribute(allow_empty_injection<derived_shared_pointer_source<B, U>>) -> std::true_type;
376+
};
377+
205378
KANGARU5_EXPORT template<source Source, source Alternative>
206379
struct with_alternative {
207380
constexpr with_alternative(Source source, Alternative alternative) noexcept : source{std::move(source)}, alternative{std::move(alternative)} {}

0 commit comments

Comments
 (0)