Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ Status labels:

## FINISHED

Completed on `main` (unreleased):

- `has<...>` is tuple-like: `auto [x, y] = has<&Point::x, &Point::y>;`
declares member-anchored guard placeholders without a macro.
- `PTN_BIND` is deprecated in favor of structured-binding member names.
It remains supported, and is still needed for function-local names
inside `PTN_ON` in C++17.
- Bare `is<T>` and `alt<I>` reach the static variant dispatch fast path.

Completed in [v0.9.4](changelog/v0.9.4.md):

- `PTN_BIND(Type, names...)` member-anchored named guard
Expand Down Expand Up @@ -111,4 +120,4 @@ here so they are not re-proposed without new motivation.
with explicit range modes.
- **`PTN_BIND` `Type` validation**: resolved without reflection —
names now expand to `member_t<&Type::name>`, so member checking
happens at declaration time (see WIP above).
happens at declaration time (shipped in v0.9.4).
6 changes: 3 additions & 3 deletions docs/tutorials/other-languages.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ auto label = match(x) | on(
Without native language destructuring, Patternia uses explicit member pointers:

```cpp
PTN_BIND(User, age, active);
constexpr auto u = has<&User::age, &User::active>;
auto [age, active] = u;

auto label = match(user) | on(
$(has<&User::age, &User::active>)[age < 18 && active == true]
>> "minor",
$(u)[age < 18 && active == true] >> "minor",
_ >> "adult"
);
```
Expand Down
16 changes: 13 additions & 3 deletions docs/tutorials/policy-constraint.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,27 @@ struct Request {
## Naming Domain Predicates

```cpp
auto is_public_resource = [](int id) {
auto is_public_resource = [](Role, int id) {
return id >= 0 && id < 1000;
};
```

A callable guard receives every member listed in `has<...>`, in order. The
rule below lists `role` and `resource_id`, so the predicate takes both, even
though it only inspects the id.

## Declaring the Rules

```cpp
bool allowed(const Request &req) {
using namespace ptn;
PTN_BIND(Request, role, resource_id, read_only);
constexpr auto request =
has<&Request::role, &Request::resource_id, &Request::read_only>;
auto [role, resource_id, read_only] = request;

return match(req) | on(
$(has<&Request::role>)[_ == Role::Admin] >> true,
$(has<&Request::role, &Request::resource_id, &Request::read_only>)
$(request)
[role == Role::User && resource_id >= 0 && read_only == true] >> true,
$(has<&Request::role, &Request::resource_id>)
[role == Role::Guest && is_public_resource] >> true,
Expand All @@ -52,3 +58,7 @@ Each rule is self-contained:
- the handler states the outcome

That keeps policy code readable even when ordering matters.

The names declared from `request` follow members, not positions, so the
third rule can use `role` with a pattern that lists only `role` and
`resource_id`.
15 changes: 8 additions & 7 deletions docs/tutorials/sphere-constraint.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,21 +34,22 @@ const char *classify(const Vec3 &p) {

## Refining the Constraint

You can combine a named predicate with a `PTN_BIND` placeholder for simple
extra checks:
You can combine a named predicate with a structured-binding member name for
simple extra checks:

```cpp
const char *classify_upper(const Vec3 &p) {
using namespace ptn;
PTN_BIND(Vec3, x, y, z);
constexpr auto xyz = has<&Vec3::x, &Vec3::y, &Vec3::z>;
auto [x, y, z] = xyz;

return match(p) | on(
$(has<&Vec3::x, &Vec3::y, &Vec3::z>)[z >= 0 && inside_unit_sphere]
>> "inside",
$(xyz)[z >= 0 && inside_unit_sphere] >> "inside",
_ >> "outside"
);
}
```

For multi-value guards, prefer `PTN_BIND` names or a callable that accepts all
bound values.
For multi-value guards, prefer structured-binding member names or a callable
that accepts all bound values. Only `z` is used here; unused names such as `x`
and `y` are fine.
Loading