Aria 2.0.0
C++23 MVVM framework (C++20 minimum) — reactive, coroutine-first, ABI-layered
Loading...
Searching...
No Matches
concepts.hpp
Go to the documentation of this file.
1#pragma once
2
3// ============================================================================
4// aria/concepts.hpp
5// ----------------------------------------------------------------------------
6// Central catalogue of public-facing concepts used across the framework.
7//
8// Per `docs/api-style.md` S-30, every templated public entry point should
9// prefer a named concept here over inline `requires` clauses. That way
10// IDEs and compilers can both surface a one-line "constraint not
11// satisfied" diagnostic instead of a multi-screen SFINAE explosion.
12//
13// Concepts live in `aria::` so users never have to qualify them with
14// `aria::reactive::` or any other implementation namespace.
15// ============================================================================
16
17#include <concepts>
18#include <functional>
19#include <optional>
20#include <type_traits>
21
22namespace aria {
23
24// ---------------------------------------------------------------------------
25// Equality / property-value primitives
26// ---------------------------------------------------------------------------
27
29template<typename T>
30concept EqualityComparable = requires(const T& a, const T& b) {
31 { a == b } -> std::convertible_to<bool>;
32 { a != b } -> std::convertible_to<bool>;
33};
34
37template<typename F, typename Ret, typename... Args>
38concept InvocableR = std::invocable<F, Args...>
39 && std::convertible_to<std::invoke_result_t<F, Args...>, Ret>;
40
49template<typename T>
50concept Observable = requires(T t) {
51 typename T::value_type;
52 { t.get() } -> std::convertible_to<typename T::value_type>;
53};
54
61template<typename T>
62concept PropertyValue = std::copyable<T> && EqualityComparable<T>;
63
64// ---------------------------------------------------------------------------
65// Read-only reactive sources
66// ---------------------------------------------------------------------------
67
87template<typename S>
89 requires(S& s) {
90 typename S::value_type;
91 { s.get() } -> std::convertible_to<typename S::value_type>;
92 } &&
93 requires(S& s, std::function<void(const typename S::value_type&)> fn) {
94 s.on_changed(std::move(fn));
95 };
96
100template<typename S, typename T>
102 && std::same_as<typename S::value_type, T>;
103
104namespace detail {
105
106template<typename T> struct is_optional : std::false_type {};
107template<typename U> struct is_optional<std::optional<U>> : std::true_type {};
108
109template<typename T>
110inline constexpr bool is_optional_v = is_optional<T>::value;
111
112} // namespace detail
113
117template<typename S>
119 && detail::is_optional_v<typename S::value_type>;
120
121// ---------------------------------------------------------------------------
122// Reactive graph participation
123// ---------------------------------------------------------------------------
124//
125// `aria::ReactiveNode<T>` (constraining types that play in the dependency
126// graph, i.e. inherit `aria::reactive::Node`) is defined alongside its
127// required complete type in `<aria/reactive/node.hpp>`. Including it
128// here would force every `<aria/concepts.hpp>` consumer to drag the
129// whole reactive subsystem; users that need `ReactiveNode` will already
130// be including `<aria/property.hpp>` (or similar) which transitively
131// pulls it in, so the concept is still surfaced from `aria::`.
132
133} // namespace aria
Type that supports == and != (required for change detection).
Definition concepts.hpp:30
Anything that can be invoked with Args... and returns convertible-to-Ret.
Definition concepts.hpp:38
A read-only observable: has .get() and exposes its value_type.
Definition concepts.hpp:50
Type usable as a Property value:
Definition concepts.hpp:62
A reactive cell that can be read and observed, but not written: exactly the surface a one-way (VM→Vie...
Definition concepts.hpp:88
ReadOnlyReactive pinned to a specific value type — the constraint for the typed scalar binders (bind_...
Definition concepts.hpp:101
A ReadOnlyReactive whose value_type is some std::optional<U> — the shape of AsyncCommand::last_result...
Definition concepts.hpp:118
Definition signal.hpp:12
Definition validation_key.hpp:110