Skip to content

sum::transform with a void-returning callback hard-errors in the collapsing machinery instead of being non-viable #294

Description

@Bronek

The sum arm of invocable_transform_error asks

{ FWD(v).error().transform(FWD(fn)) } -> convertible_to_expected<...>;

and for a void-returning callback the question does not answer — it explodes while forming sum::transform's return type: the collapsing machinery computes the flattened, normalized sum of the per-alternative invoke results, and a void result has no place in that computation, which fails outside any immediate context.

#include <fn/transform_error.hpp>
#include <fn/sum.hpp>

struct A final {};
struct B final {};
constexpr auto fnVoid = [](auto &&...) -> void {};

static_assert(not fn::invocable_transform_error<decltype(fnVoid), fn::expected<int, fn::sum_for<A, B>>>);

hard-errors on g++ and clang. The defect is in the machinery, not the concept — the same formation is reachable directly:

template <typename S, typename Fn>
concept can_transform = requires(S s, Fn fn) { static_cast<S &&>(s).transform(fn); };

static_assert(not can_transform<fn::sum_for<A, B> &, decltype(fnVoid)>);

is a hard error too. So a void guard on the concept would cover only the verb path; sum::transform (and whatever else forms this return type) needs to reject a void-producing callback in the immediate context. Distinct mechanism from #290/#293 (a result-type computation, not a conversion-target mandate) — needs its own investigation.

Reproduced at 58d131c with gcc 16.1.1 and clang 22.1.6 (x86-64 Linux).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingrelease-0.1Planned for release 0.1

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions