cuda::experimental::stf::sump::dynamic#

class dynamic#

A type-erased exception policy: any policy behind one concrete type.

The shell interprets at decltype(fn()). Erasure boxes answers as std::any internally; that box reaches the user only when the callable itself returns std::any. Retrying policies keep their internal loops, state, and rethrow-on-exhaustion; composites erase whole; a sink composes with &, |, *, when, always and re-erases. The checks that |, &, and * perform statically run against the erased policy’s metadata when the composite is built, and throw std::logic_error on a dead arm: a dynamic that never passes through or always diverges to the left of | or under *, and one that chooses a value or never returns to the left of &.

Custom runtime policies derive from the public sink_base and implement hook (and clone); on_success defaults to identity. Erasure records the static properties the checks use (produces_value, diverges, may_passthrough, the selector flags), so an erased policy is checked exactly as its static form. Hand-written models default to own_result with permissive flags, which pass every check. Erased |-composites are own_result (a loud, value-checked unbox on first throw is their backstop); a pure-& composite keeps its final policy’s precise kind and is checked at first use. A wrapped success channel that cannot accept std::any (for example remember) does not survive erasure.

LIMIT: std::any cannot carry references. A reference-returning callable is rejected at the composition site; use a concrete policy, or return a pointer.

Public Types

enum class answer_kind#

What the wrapped policy’s answer was, statically, at erasure time.

Values:

enumerator dies#

the hook never returns (answered nullval)

enumerator resumes#

resume (answered std::ignore)

enumerator effects#

side effect only (answered void)

enumerator integral#

a stored integral or enumeration, with a value range

enumerator floating#

a stored floating value (precision loss under a floating body is tolerated)

enumerator udt#

a stored class, pointer, or other exact-match type

enumerator own_result#

the boxed value is the callable’s own result (std::any)

Public Functions

template<class _P, ::cuda::std::enable_if_t<!::cuda::std::is_same_v<::cuda::std::remove_cvref_t<_P>, dynamic>, int> = 0, ::cuda::std::enable_if_t<detail::__normalizes_to_exception_sink_v<_P>, int> = 0>
inline dynamic(
_P &&__p
)#

Erase a policy.

Implicit, so any sink converts where a dynamic is expected: void release_all(pool&, dynamic sink); release_all(pl, notify & abort);. A raw reaction is normalized first. The dynamic exclusion is a separate template parameter so that substitution stops there for dynamic itself ([temp.deduct]/7, lexical order): otherwise __normalize(const dynamic&), whose copy considers this constructor, would ask for __normalized_t<const dynamic&>, i.e. its own return type while it is being deduced (EDG/nvcc: “cannot deduce the return type … it has not been defined”).

inline explicit dynamic(::std::unique_ptr<sink_base> __custom)#

Adopt a custom model derived from sink_base.

inline dynamic(const dynamic &__other)#
dynamic(dynamic&&) noexcept = default#
dynamic &operator=(dynamic&&) noexcept = default#
inline dynamic &operator=(const dynamic &__other)#
inline answer_kind kind() const noexcept#
inline bool may_passthrough() const noexcept#

Whether the erased policy may pass an error through (false: alternatives after this sink are unreachable).

inline bool may_throw() const noexcept#

Whether the erased policy may throw.

inline bool diverges() const noexcept#

Whether the erased policy always diverges (unwind, abort, terminate).

inline bool produces_value() const noexcept#

Whether the erased policy’s answer is a value standing in for the expression’s.

inline bool needs_future() const noexcept#

Whether the erased policy re-runs the action.

inline bool selects_thrown() const noexcept#

Whether the erased policy selects exceptions by type.

inline bool selects_returned() const noexcept#

Whether the erased policy selects failing statuses.

inline bool may_rethrow() const noexcept#

Former name of may_passthrough (deprecated).

template<class _Fn, class _Raw = decltype(::cuda::std::declval<_Fn&>()())>
inline auto on_thrown(
const ::std::exception *__e,
const ::cuda::std::source_location __loc,
_Fn &__fn
) -> ::cuda::std::conditional_t<::cuda::std::is_void_v<_Raw>, decltype(::std::ignore), _Raw>#

The uniform hook: answers decltype(fn()).

A void callable answers decltype(::std::ignore) so the presence-probe archetype stays admissible.

inline void on_enter()#

Entry gate: forwards to the erased policy (no-op when it has none).

template<class _R>
inline _R on_success(_R &&__r)#

Type-preserving success pass-through: box, delegate, unbox to the same type.

inline void on_success()#
struct sink_base#

The erasure surface.

Public: custom runtime policies derive from it and implement hook (forward by throwing; hand back std::any, empty meaning “no value”) and clone; on_success defaults to identity.

Public Functions

inline sink_base(
answer_kind __kind = answer_kind::own_result,
bool __may_passthrough = true,
long long __min_value = 0,
unsigned long long __max_value = 0,
const ::std::type_info *__answer_type = nullptr,
::std::string_view __answer_name = {},
bool __diverges = false,
bool __produces_value = false,
bool __needs_future = false,
bool __selects_thrown = false,
bool __selects_returned = false,
bool __has_success_hook = true
)#
virtual ~sink_base() = default#
virtual sink_base *clone() const = 0#
virtual ::std::any hook(
const ::std::exception*,
::cuda::std::source_location,
::std::function<::std::any()>&
) = 0#
inline ::std::any on_success(::std::any __boxed)#
inline ::std::any on_success()#
inline virtual void on_enter()#

Entry gate, run before each attempt. Default: admit.

Public Members

const answer_kind kind#
const bool may_passthrough#

Whether the policy may pass an error through (false: alternatives after this sink are unreachable).

Conservative for hand-written models.

const bool may_throw#

Whether the policy may throw.

Equal to may_passthrough for now: on the exception channel the only way out of a hook is a throw.

const bool diverges#

Whether the policy always diverges (unwind, abort, terminate): alternatives and repetitions after it are unreachable even though it passes an exception through.

const bool produces_value#

Whether the policy’s answer is a value standing in for the expression’s (subst, as_expected, defer, retry, a converter): a sequence after it would discard or override that value.

const bool needs_future#

Whether the policy re-runs the action, which a status operand does not have.

const bool selects_thrown#

Whether the policy contains a selector that matches exceptions by type (if_isa, thrown).

const bool selects_returned#

Whether the policy contains a selector that matches failing statuses (if_equal, returned).

const long long min_value#

Inclusive range of a stored integral answer; unused for other kinds.

const unsigned long long max_value#
const ::std::type_info *answer_type#

Exact stored type for udt checks; nullptr encodes own_result.

const ::std::string_view answer_name#
const bool has_success_hook#

Whether the wrapped policy has a success hook at all.

When it has none, the shell returns the callable’s value unboxed: the success path of an erased sink then costs the virtual-free fast path rather than a std::any round trip. Conservative (true) for hand-written models.