Skip to content

Add the apply family to optional and expected, with trailing arguments throughout - #343

Merged
Bronek merged 4 commits into
mainfrom
bronek/apply_type_optional_expected
Jul 17, 2026
Merged

Add the apply family to optional and expected, with trailing arguments throughout#343
Bronek merged 4 commits into
mainfrom
bronek/apply_type_optional_expected

Conversation

@Bronek

@Bronek Bronek commented Jul 17, 2026

Copy link
Copy Markdown
Member

Two deliveries in four commits, the second building directly on the first.

optional and expected gain the apply family (#339)

apply, apply_r, apply_type and apply_type_r eliminate both states through one callable — the lower-level tool beside the monadic members, as on sum and choice (#268). Both arms are required outright and must agree on one result type (apply_r converts). The untagged apply hands each state's content over exactly as fn::apply would — a pack or tuple-like payload by elements, a sum payload by dispatch, anything else (including a choice, a nominal boundary) whole — and the empty arm of optional is invoked without a value. apply_type keys each arm by the constructor tag that names the state — std::in_place for the held value, std::nullopt for empty, fn::unexpect for the error — so the dispatch is airtight by construction even where T and E interconvert: a lone double arm silently serves both rows of expected<double, int> on the untagged path, while the tags never convert. As on sum::apply_type, a tuple-like payload's elements form is the tagged row's one signature (no pass-whole fallback; the untagged path keeps it), and within a sum payload the dispatch stays the value path — the tag guards the state, not the sum's rows.

The engine route makes the composition automatic: both arms eliminate through the same machinery fn::apply uses (probe==deed via the _is_applicable families and the new _apply_tagged dispatchers), and the empty/void arms receive their tag as a prvalue, the exact shape the traits ask about.

Trailing arguments become uniform across the family (#342)

sum::apply/apply_r always accepted trailing arguments — the member leg of fn::apply's engine protocol. Nothing ever forced that shape onto apply_type/apply_type_r (no free-function counterpart) or onto choice (an atom the free apply never dispatches), while the internal type-indexed machinery anticipated the arguments all along. Rectified additively: apply_type/apply_type_r on all four types, and choice's apply/apply_r, now take trailing arguments appended after each arm's unpacked content; the type-indexed trait families and union walkers thread them exactly as their value-path twins do.

One MSVC portability lesson is baked into the implementation: a constrained-out declaration must not name tuple_size raw (MSVC substitutes eagerly where gcc/clang stop at the failed constraint), so the tuple-like arms specify themselves through _elems_traits/_elems_traits_r, gated in the shape of pfn's _apply_traits.

Verified on gcc and clang across Debug/Release and both VALIDATE_CXX23 lanes, and on MSVC (build and ctest) at each delivery point.

Closes #339
Closes #342

🤖 Generated with Claude Code

Bronek added 4 commits July 17, 2026 12:41
Assisted-by: Claude:claude-fable-5
Assisted-by: Claude:claude-fable-5
@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.52607% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
include/fn/expected.hpp 98.2% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@sonarqubecloud

Copy link
Copy Markdown

@augmentcode

augmentcode Bot commented Jul 17, 2026

Copy link
Copy Markdown
🤖 Augment PR Summary

Summary: This PR introduces the full apply elimination family for fn::optional and fn::expected, and makes trailing “extra” arguments consistent across the typed/tagged apply APIs.

Changes:

  • Adds apply/apply_r/apply_type/apply_type_r to optional and expected, mirroring sum/choice elimination semantics (including void/value-state nuances).
  • Extends choice::apply/apply_r and apply_type/apply_type_r (and sum::apply_type/apply_type_r) to accept trailing arguments after the unpacked payload.
  • Enhances internal dispatch machinery in fn/detail/functional.hpp to support tagged elimination and tuple-like element unpacking with trailing arguments.
  • Updates variadic_union type-indexed dispatch to thread trailing arguments through invocations.
  • Adds comprehensive tests for optional and expected apply behavior (value categories, void-value expected, pack/tuple-like/sum payloads, extra args) and extends sum/choice tests for the new trailing-args shape.
  • Records the design transitions in CHANGELOG.md.

Technical Notes: Introduces MSVC-friendly tuple-like probing (avoiding eager tuple_size substitution in constrained-out candidates) and ensures tags are passed as prvalues for airtight dispatch.

🤖 Was this summary useful? React with 👍 or 👎

@augmentcode augmentcode Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. No suggestions at this time.

Comment augment review to trigger a new review at any time.

@Bronek
Bronek merged commit 284204f into main Jul 17, 2026
66 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Accept trailing arguments uniformly across the apply family Add apply and apply_type to optional and expected

1 participant