Skip to content

when_all: replace void filtering with monostate to preserve task-index-to-result-index mapping #204

@mvandeberg

Description

@mvandeberg

Problem

when_any (variadic) returns a std::variant<void_to_monostate_t<Ts>...>, replacing void-returning tasks with std::monostate so that .index() maps directly to the input task index. This is correct and useful.

when_all (variadic) uses filter_void_tuple_t which removes void types entirely from the result tuple via tuple_cat. This breaks the task-index-to-result-index invariant.

Example

auto [a, b] = co_await when_all(
    fetch_int(),     // task<int>   — index 0
    log_something(), // task<void>  — index 1
    fetch_str()      // task<string> — index 2
);
// a = int (from task 0) ✓
// b = string (from task 2), but accessed via get<1> ✗
// No entry for task 1 — tuple indices don't correspond to task indices

With monostate replacement (matching when_any's approach):

auto [a, b, c] = co_await when_all(
    fetch_int(),     // task<int>        — index 0
    log_something(), // task<void>       — index 1
    fetch_str()      // task<string>     — index 2
);
// a = int (from task 0)        — get<0> ✓
// b = monostate (from task 1)  — get<1> ✓
// c = string (from task 2)     — get<2> ✓

Proposed Fix

Replace the void-filtering logic in when_all with void_to_monostate_t (already defined in when_any.hpp), mirroring the approach used by when_any:

  • Result type: std::tuple<void_to_monostate_t<awaitable_result_t<As>>...>
  • result_holder<void> stores/returns std::monostate instead of being empty
  • extract_results returns monostate for void tasks instead of filtering them out
  • All-void case returns std::tuple<std::monostate, ...> instead of void

This is a breaking API change for any code using when_all with a mix of void and non-void tasks, or relying on the all-void → task<void> return.

Affected Files

  • include/boost/capy/when_all.hpp
  • test/unit/when_all.cpp
  • Potentially doc examples

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions