|
1 | | -# Handoff: After Fix 3 |
| 1 | +# Handoff: After Fix 4 |
2 | 2 |
|
3 | 3 | ## What Was Done |
4 | 4 |
|
5 | | -Fix 3 is complete. SFINAE-friendly `requires` clauses added to all monadic |
6 | | -operations per standard Constraints. Branch `fix3-monadic-constraints` merged |
7 | | -(--no-ff) into `expected-over-references`. |
| 5 | +Fix 4 is complete. `static_assert` Mandates added to observers and monadic |
| 6 | +operations per standard wording. Branch `fix4-mandates` merged (--no-ff) into |
| 7 | +`expected-over-references`. |
8 | 8 |
|
9 | 9 | ### Changes in `include/beman/expected/expected.hpp` |
10 | 10 |
|
11 | | -**Primary template (16 overloads — 4 operations × 4 ref-qualifiers):** |
12 | | -- `and_then` / `transform`: `requires std::is_constructible_v<E, E-ref>` |
13 | | - (E& for &, E&& for &&, const E& for const&, const E&& for const&&) |
14 | | -- `or_else` / `transform_error`: `requires std::is_constructible_v<T, T-ref>` |
15 | | - (same ref-qualifier pattern) |
| 11 | +**Primary template class-level:** |
| 12 | +- `static_assert(!detail::is_unexpected_specialization<remove_cv_t<T>>::value, ...)` |
16 | 13 |
|
17 | | -**Void specialization (8 of 16 overloads):** |
18 | | -- `and_then` / `transform`: same E-constructibility constraints as primary |
19 | | -- `or_else` / `transform_error`: NO constraints (standard specifies none) |
| 14 | +**Primary template `value()` (4 overloads):** |
| 15 | +- `const&` / `&`: `is_copy_constructible_v<E>` |
| 16 | +- `&&` / `const&&`: `is_copy_constructible_v<E> && is_constructible_v<E, decltype(std::move(error()))>` |
20 | 17 |
|
21 | | -Both in-class declarations and out-of-line definitions updated. |
| 18 | +**Primary template `value_or()` (2 overloads):** |
| 19 | +- `const&`: `is_copy_constructible_v<T>`, `is_convertible_v<U, T>` |
| 20 | +- `&&`: `is_move_constructible_v<T>`, `is_convertible_v<U, T>` |
| 21 | + |
| 22 | +**`error_or()` (4 overloads — both primary and void):** |
| 23 | +- `const&`: `is_copy_constructible_v<E>`, `is_convertible_v<G, E>` |
| 24 | +- `&&`: `is_move_constructible_v<E>`, `is_convertible_v<G, E>` |
| 25 | + |
| 26 | +**Void specialization `value()` (2 overloads):** |
| 27 | +- `const&`: `is_copy_constructible_v<E>` |
| 28 | +- `&&`: `is_copy_constructible_v<E> && is_move_constructible_v<E>` |
| 29 | + |
| 30 | +**`transform()` (8 overloads — both primary and void):** |
| 31 | +- In `if constexpr (!is_void_v<U>)` block: U not array, not in_place_t, not unexpect_t, not unexpected<> |
| 32 | + |
| 33 | +**`transform_error()` (8 overloads — both primary and void):** |
| 34 | +- G is object, not array, not cv-qualified, not unexpected<> |
22 | 35 |
|
23 | 36 | ### Tests added |
24 | 37 |
|
25 | | -- `tests/beman/expected/expected_monadic_constraints.test.cpp` — beman-only: |
26 | | - - Concept detectors using `std::declval<X>()` to preserve value category |
27 | | - - MoveOnly type (deleted copy ctor) as E: verifies `and_then`/`transform` |
28 | | - lvalue overloads are SFINAE-removed, rvalue overloads remain available |
29 | | - - MoveOnly type as T: verifies `or_else`/`transform_error` same pattern |
30 | | - - Void specialization: same E-constructibility tests for `and_then`/`transform` |
31 | | - - Void specialization: `or_else`/`transform_error` unconstrained (always available) |
32 | | - - Normal types: all operations remain available on all overloads |
33 | | - - 6 Catch2 runtime tests exercising rvalue monadic chains with move-only types |
| 38 | +- `tests/beman/expected/expected_unexpected_value_type_fail.cpp` — negative compile |
| 39 | + test verifying `expected<unexpected<int>, int>` is ill-formed |
34 | 40 |
|
35 | 41 | ### Test count |
36 | 42 |
|
37 | | -247 tests total, all passing. |
| 43 | +248 tests total, all passing. |
38 | 44 |
|
39 | 45 | ## Build Commands |
40 | 46 |
|
41 | 47 | ```bash |
42 | | -make TOOLCHAIN=gcc-16 test # 247 tests, all passing |
| 48 | +make TOOLCHAIN=gcc-16 test # 248 tests, all passing |
43 | 49 | make lint # all linters pass (beman-tidy crash is pre-existing) |
44 | 50 | ``` |
45 | 51 |
|
46 | 52 | ## Conformance Fix Checklist |
47 | 53 |
|
48 | 54 | - [x] Fix 1: Constructor/assignment/equality constraints |
49 | 55 | - [x] Fix 2: Trivial special member functions |
50 | | -- [x] Fix 3: Monadic operation constraints ← just done |
51 | | -- [ ] Fix 4: Mandates static_asserts |
| 56 | +- [x] Fix 3: Monadic operation constraints |
| 57 | +- [x] Fix 4: Mandates static_asserts ← just done |
52 | 58 | - [ ] Fix 5: Hardened preconditions and minor fixes |
53 | 59 |
|
54 | | -## Next Step: Fix 4 |
| 60 | +## Next Step: Fix 5 |
55 | 61 |
|
56 | | -Fix 4 adds `static_assert` Mandates to observers and monadic operations. |
57 | | -These go on the same functions that just received requires clauses (Fix 3), |
58 | | -plus `value()`, `value_or()`, and `error_or()` observers. |
| 62 | +Fix 5 adds hardened precondition checks to observers (`operator->`, `operator*`, |
| 63 | +`error()`) and miscellaneous minor fixes (friend swap constraint on |
| 64 | +`unexpected<E>`, etc.). |
59 | 65 |
|
60 | | -The Mandates are compile-time checks that produce clear diagnostics when |
61 | | -violated, as opposed to Constraints which affect overload resolution. |
62 | | -See `docs/conformance-fixes/fix4-mandates.md`. |
| 66 | +See `docs/conformance-fixes/fix5-preconditions-and-minor.md`. |
0 commit comments