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+
2226namespace 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