YOrch 1.0.0
Loading...
Searching...
No Matches
resolve.hpp
Go to the documentation of this file.
1#pragma once
2#include <functional>
3#include <type_traits>
4#include <utility>
5#include "context.hpp"
6#include "specs.hpp"
7
8namespace yorch::detail {
9
10template <typename>
11inline constexpr bool always_false_v = false;
12
13template <typename Arg, typename Source>
14inline constexpr bool supports_bind_from_lvalue_v =
15 !std::is_rvalue_reference_v<Arg> &&
16 (
17 std::is_reference_v<Arg> ||
18 std::is_constructible_v<std::remove_cvref_t<Arg>, Source&>
19 );
20
21template <typename Arg, typename Source>
22inline constexpr bool bind_from_lvalue_nothrow_v =
24 (
25 std::is_reference_v<Arg> ||
26 std::is_nothrow_constructible_v<std::remove_cvref_t<Arg>, Source&>
27 );
28
29template <typename T>
31
32template <typename T>
34
35template <typename T>
37
38template <typename T>
40
41template <typename T>
43
44template <typename Ctx, typename T>
45inline constexpr bool ctx_get_nothrow_v =
46 noexcept(std::declval<Ctx&>().template get<from_ctx_source_t<T>>());
47
48template <typename Prev, typename Source>
49inline constexpr bool prev_get_source_nothrow_v =
50 noexcept(std::declval<Prev&>().template get<Source>());
51
52template <typename Arg, typename T, typename Ctx>
53inline constexpr bool resolve_from_ctx_nothrow_v =
56
57template <typename Arg, typename T, typename Prev>
58inline constexpr bool resolve_borrow_prev_nothrow_v =
60
61template <typename Arg, typename T, typename Prev>
62inline constexpr bool resolve_borrow_prev_mut_nothrow_v =
64
65template <typename T, typename Prev>
66inline constexpr bool resolve_copy_prev_nothrow_v =
68 std::is_nothrow_constructible_v<
69 std::remove_cvref_t<copy_prev_source_t<T>>,
70 const std::remove_cvref_t<copy_prev_source_t<T>>&>;
71
72template <typename Arg, typename T>
73inline constexpr bool consume_bind_nothrow_v =
74 std::is_same_v<Arg, std::remove_cvref_t<T>&&> ||
75 std::is_nothrow_constructible_v<std::remove_cvref_t<Arg>, std::remove_cvref_t<T>&&>;
76
77template <typename Arg, typename T, typename Prev>
78inline constexpr bool resolve_consume_prev_nothrow_v =
81
82template <typename Arg, typename T>
83inline constexpr bool resolve_value_nothrow_v =
84 std::is_reference_v<Arg> ||
85 std::is_nothrow_constructible_v<std::remove_cvref_t<Arg>, T&>;
86
87template <typename Arg, typename T>
88inline constexpr bool resolve_const_value_nothrow_v =
89 std::is_reference_v<Arg> ||
90 std::is_nothrow_constructible_v<std::remove_cvref_t<Arg>, const T&>;
91
92} // namespace yorch::detail
93
94namespace yorch {
95
96template <typename Arg, typename Source>
99
100template <typename Arg, typename T>
102 !std::is_rvalue_reference_v<Arg> &&
103 (
104 (
105 std::is_reference_v<Arg> &&
106 std::is_const_v<std::remove_reference_t<Arg>> &&
107 std::is_convertible_v<T&, const std::remove_cvref_t<Arg>&>
108 ) ||
109 (
110 !std::is_reference_v<Arg> &&
111 std::is_constructible_v<std::remove_cvref_t<Arg>, T&>
112 )
113 );
114
115template <typename Arg, typename T>
117 !std::is_rvalue_reference_v<Arg> &&
118 (
119 (
120 std::is_reference_v<Arg> &&
121 std::is_const_v<std::remove_reference_t<Arg>> &&
122 std::is_convertible_v<const T&, const std::remove_cvref_t<Arg>&>
123 ) ||
124 (
125 !std::is_reference_v<Arg> &&
126 std::is_constructible_v<std::remove_cvref_t<Arg>, const T&>
127 )
128 );
129
149template <typename Arg, typename Source>
151constexpr decltype(auto) bind_from_lvalue(Source& src)
154 "Does not support binding to T&&");
155
156 using raw_arg_t = std::remove_cvref_t<Arg>;
157
158 if constexpr (std::is_reference_v<Arg>) {
159 if constexpr (std::is_const_v<std::remove_reference_t<Arg>>) {
160 static_assert(std::is_convertible_v<Source&, const raw_arg_t&>,
161 "Source cannot bind to const reference argument");
162 return static_cast<const raw_arg_t&>(src);
163 } else {
164 static_assert(std::is_convertible_v<Source&, raw_arg_t&>,
165 "Source cannot bind to non-const reference argument");
166 return static_cast<raw_arg_t&>(src);
167 }
168 } else {
169 static_assert(std::is_constructible_v<raw_arg_t, Source&>,
170 "Source cannot be copied/converted into value argument");
171 return static_cast<raw_arg_t>(src);
172 }
173}
174
190template <typename Arg, typename T, typename Ctx, typename Prev>
193 static_assert(!std::is_void_v<Ctx>,
194 "from_ctx<T>() cannot be used with exec_context<void>");
195
196 using source_t = typename from_ctx_t<T>::type;
197
198 static_assert(Ctx::template contains<source_t>(),
199 "Requested type is not present in the context");
200
201 auto& src = ec.ctx.template get<source_t>();
202 return bind_from_lvalue<Arg>(src);
203}
204
219template <typename Arg, typename T, typename Ctx, typename Prev>
222 using source_t = typename borrow_prev_t<T>::type;
223 using prev_t = std::remove_cvref_t<decltype(ec.prev_view())>;
224
225 static_assert(std::is_same_v<Arg, const source_t&>,
226 "borrow_prev<T>() only binds to const T&");
227 static_assert(prev_t::template contains<source_t>(),
228 "borrow_prev<T>() requires a direct parent slot carrying the requested type");
229
230 auto& src = ec.prev_view().template get<source_t>();
231 return static_cast<const source_t&>(src);
232}
233
241template <typename Arg, typename T, typename Ctx, typename Prev>
244 using source_t = typename borrow_prev_mut_t<T>::type;
245 using prev_t = std::remove_cvref_t<decltype(ec.prev_view())>;
246 using prev_ref_t = decltype(std::declval<Prev&>().template get<source_t>());
247
248 static_assert(std::is_same_v<Arg, source_t&>,
249 "borrow_prev_mut<T>() only binds to T&");
250 static_assert(prev_t::template contains<source_t>(),
251 "borrow_prev_mut<T>() requires a direct parent slot carrying the requested type");
252 static_assert(!std::is_const_v<std::remove_reference_t<prev_ref_t>>,
253 "borrow_prev_mut<T>() requires a mutable direct parent payload source");
254
255 auto& src = ec.prev_view().template get<source_t>();
256 return static_cast<source_t&>(src);
257}
258
266template <typename Arg, typename T, typename Ctx, typename Prev>
269 using source_t = typename copy_prev_t<T>::type;
270 using prev_t = std::remove_cvref_t<decltype(ec.prev_view())>;
271
272 static_assert(std::is_same_v<Arg, source_t>,
273 "copy_prev<T>() only binds to T");
274 static_assert(prev_t::template contains<source_t>(),
275 "copy_prev<T>() requires a direct parent slot carrying the requested type");
276 static_assert(std::is_constructible_v<source_t, const source_t&>,
277 "copy_prev<T>() requires T to be constructible from const T&");
278
279 auto& src = ec.prev_view().template get<source_t>();
280 return static_cast<source_t>(static_cast<const source_t&>(src));
281}
282
290template <typename Arg, typename T, typename Ctx, typename Prev>
293 using source_t = typename consume_prev_t<T>::type;
294 using prev_t = std::remove_cvref_t<decltype(ec.prev_view())>;
295 using prev_ref_t = decltype(std::declval<Prev&>().template get<source_t>());
296
297 static_assert(std::is_same_v<Arg, source_t> || std::is_same_v<Arg, source_t&&>,
298 "consume_prev<T>() only binds to T or T&&");
299 static_assert(prev_t::template contains<source_t>(),
300 "consume_prev<T>() requires a direct parent slot carrying the requested type");
301 static_assert(!std::is_const_v<std::remove_reference_t<prev_ref_t>>,
302 "consume_prev<T>() requires a mutable direct parent payload source");
303
304 auto& src = ec.prev_view().template get<source_t>();
305
306 if constexpr (std::is_same_v<Arg, source_t&&>) {
307 return static_cast<source_t&&>(src);
308 } else {
309 return static_cast<source_t>(std::move(src));
310 }
311}
312
332template <typename Arg, typename T, typename Ctx, typename Prev>
333constexpr decltype(auto) resolve_as(value_t<std::reference_wrapper<T>>& spec, exec_context<Ctx, Prev>&)
334 noexcept(std::is_reference_v<Arg>) {
335 static_assert(std::is_reference_v<Arg>,
336 "value(std::ref(...)) can only bind to T& or const T&");
337
338 using raw_arg_t = std::remove_cvref_t<Arg>;
339 auto& ref = spec.v.get();
340
341 if constexpr (std::is_const_v<std::remove_reference_t<Arg>>) {
342 static_assert(std::is_convertible_v<T&, const raw_arg_t&>,
343 "Stored reference_wrapper cannot bind to requested const reference type");
344 return static_cast<const raw_arg_t&>(ref);
345 } else {
346 static_assert(std::is_convertible_v<T&, raw_arg_t&>,
347 "Stored reference_wrapper cannot bind to requested mutable reference type");
348 return static_cast<raw_arg_t&>(ref);
349 }
350}
351
352template <typename Arg, typename T, typename Ctx, typename Prev>
353constexpr decltype(auto) resolve_as(const value_t<std::reference_wrapper<T>>& spec, exec_context<Ctx, Prev>&)
354 noexcept(std::is_reference_v<Arg>) {
355 static_assert(std::is_reference_v<Arg>,
356 "const value(std::ref(...)) can only bind to T& or const T&");
357
358 using raw_arg_t = std::remove_cvref_t<Arg>;
359 auto& ref = spec.v.get();
360
361 if constexpr (std::is_const_v<std::remove_reference_t<Arg>>) {
362 static_assert(std::is_convertible_v<T&, const raw_arg_t&>,
363 "Stored reference_wrapper cannot bind to requested const reference type");
364 return static_cast<const raw_arg_t&>(ref);
365 } else {
366 static_assert(std::is_convertible_v<T&, raw_arg_t&>,
367 "Stored reference_wrapper cannot bind to requested mutable reference type");
368 return static_cast<raw_arg_t&>(ref);
369 }
370}
371
372template <typename Arg, typename T, typename Ctx, typename Prev>
373 requires resolvable_mutable_value<Arg, T>
374constexpr decltype(auto) resolve_as(value_t<T>& spec, exec_context<Ctx, Prev>&)
376 static_assert(!std::is_rvalue_reference_v<Arg>,
377 "Does not support binding value(...) to T&&");
378
379 using raw_arg_t = std::remove_cvref_t<Arg>;
380
381 if constexpr (std::is_reference_v<Arg>) {
382 static_assert(std::is_const_v<std::remove_reference_t<Arg>>,
383 "value(...) can only bind to T or const T&");
384 static_assert(std::is_convertible_v<T&, const raw_arg_t&>,
385 "Stored value cannot bind to requested const reference type");
386 return static_cast<const raw_arg_t&>(spec.v);
387 } else {
388 static_assert(std::is_constructible_v<raw_arg_t, T&>,
389 "Stored value cannot be copied/converted into value argument");
390 return static_cast<raw_arg_t>(spec.v);
391 }
392}
393
410template <typename Arg, typename T, typename Ctx, typename Prev>
411 requires resolvable_const_value<Arg, T>
412constexpr decltype(auto) resolve_as(const value_t<T>& spec, exec_context<Ctx, Prev>&)
414 static_assert(!std::is_rvalue_reference_v<Arg>,
415 "Does not support binding value(...) to T&&");
416
417 using raw_arg_t = std::remove_cvref_t<Arg>;
418
419 if constexpr (std::is_reference_v<Arg>) {
420 static_assert(std::is_const_v<std::remove_reference_t<Arg>>,
421 "const value(...) can only bind to T or const T&");
422 static_assert(std::is_convertible_v<const T&, const raw_arg_t&>,
423 "Stored value cannot bind to requested const reference type");
424 return static_cast<const raw_arg_t&>(spec.v);
425 } else {
426 static_assert(std::is_constructible_v<raw_arg_t, const T&>,
427 "Stored value cannot be copied/converted into value argument");
428 return static_cast<raw_arg_t>(spec.v);
429 }
430}
431
443template <typename Arg, typename Spec, typename Ctx, typename Prev>
444// NOLINTNEXTLINE(cppcoreguidelines-missing-std-forward)
445constexpr decltype(auto) resolve_as(Spec&&, exec_context<Ctx, Prev>&) {
447 "Unsupported spec in resolve_as");
448}
449
450} // namespace yorch
constexpr bool consume_bind_nothrow_v
Definition resolve.hpp:73
typename borrow_prev_t< T >::type borrow_prev_source_t
Definition resolve.hpp:33
typename borrow_prev_mut_t< T >::type borrow_prev_mut_source_t
Definition resolve.hpp:36
typename copy_prev_t< T >::type copy_prev_source_t
Definition resolve.hpp:39
constexpr bool always_false_v
Definition resolve.hpp:11
constexpr bool resolve_const_value_nothrow_v
Definition resolve.hpp:88
constexpr bool resolve_borrow_prev_nothrow_v
Definition resolve.hpp:58
constexpr bool supports_bind_from_lvalue_v
Definition resolve.hpp:14
constexpr bool resolve_value_nothrow_v
Definition resolve.hpp:83
constexpr bool resolve_borrow_prev_mut_nothrow_v
Definition resolve.hpp:62
typename consume_prev_t< T >::type consume_prev_source_t
Definition resolve.hpp:42
constexpr bool resolve_consume_prev_nothrow_v
Definition resolve.hpp:78
typename from_ctx_t< T >::type from_ctx_source_t
Definition resolve.hpp:30
constexpr bool resolve_from_ctx_nothrow_v
Definition resolve.hpp:53
constexpr bool prev_get_source_nothrow_v
Definition resolve.hpp:49
constexpr bool is_adapter_descriptor_v
Definition adapters.hpp:63
constexpr bool resolve_copy_prev_nothrow_v
Definition resolve.hpp:66
constexpr bool ctx_get_nothrow_v
Definition resolve.hpp:45
constexpr bool bind_from_lvalue_nothrow_v
Definition resolve.hpp:22
constexpr decltype(auto) resolve_as(from_ctx_t< T >, exec_context< Ctx, Prev > &ec) noexcept(detail::resolve_from_ctx_nothrow_v< Arg, T, Ctx >)
Resolves a from_ctx(...) spec by fetching the requested object from the execution context and binding...
Definition resolve.hpp:191
constexpr decltype(auto) bind_from_lvalue(Source &src) noexcept(detail::bind_from_lvalue_nothrow_v< Arg, Source >)
Binds an existing lvalue source object to the requested argument type.
Definition resolve.hpp:151
Describes a parameter that borrows the direct parent output as T&.
Definition specs.hpp:43
std::remove_cvref_t< T > type
Canonical parent payload type used for lookup.
Definition specs.hpp:45
Describes a parameter that borrows the direct parent output as const T&.
Definition specs.hpp:30
std::remove_cvref_t< T > type
Canonical parent payload type used for lookup.
Definition specs.hpp:32
Describes a parameter that consumes the direct parent output.
Definition specs.hpp:69
std::remove_cvref_t< T > type
Canonical parent payload type used for lookup.
Definition specs.hpp:71
Describes a parameter that copies the direct parent output as T.
Definition specs.hpp:56
std::remove_cvref_t< T > type
Canonical parent payload type used for lookup.
Definition specs.hpp:58
Lightweight borrowed view used during execution.
Definition context.hpp:187
constexpr Prev & prev_view() &noexcept
Definition context.hpp:194
Describes a parameter sourced from the execution context by type.
Definition specs.hpp:16
std::remove_cvref_t< T > type
Canonical context key type used for lookup.
Definition specs.hpp:18
Stores a concrete value inside a spec.
Definition specs.hpp:83
T v
Owned payload forwarded from value(...).
Definition specs.hpp:91