Date
2023-02-10.00:21:48
Message id
13317

Content

The constraints for and_then, transform, transform_error, and or_else for std::expected seem incorrect for const overloads. E.g., from [expected.object.monadic]

template<class F> constexpr auto transform(F&& f) &&;
template<class F> constexpr auto transform(F&& f) const &&;
[…]

Constraints: is_move_constructible_v<E> is true.

That constraint should likely be is_move_constructible_v<const E> for the const-qualified version. Same for the lvalue overloads, and for the three other functions, including in the void partial specialization. For example, currently this code would result in a hard compiler error inside the body of transform rather than failing the constraint:

const std::expected<int, std::unique_ptr<int>> e;
std::move(e).transform([](auto) { return 42; });

Previous resolution [SUPERSEDED]:

This wording is relative to n4928.

  1. Modify [expected.object.monadic] as indicated:

    template<class F> constexpr auto and_then(F&& f) &;
    template<class F> constexpr auto and_then(F&& f) const &;
    

    […]

    -2- Constraints: is_copy_constructible_v<Edecltype((error()))> is true.

    […]

    template<class F> constexpr auto and_then(F&& f) &&;
    template<class F> constexpr auto and_then(F&& f) const &&;
    

    […]

    -6- Constraints: is_move_constructible_v<Edecltype((error()))> is true.

    […]

    template<class F> constexpr auto or_else(F&& f) &;
    template<class F> constexpr auto or_else(F&& f) const &;
    

    […]

    -10- Constraints: is_copy_constructible_v<Tdecltype((value()))> is true.

    […]

    template<class F> constexpr auto or_else(F&& f) &&;
    template<class F> constexpr auto or_else(F&& f) const &&;
    

    […]

    -14- Constraints: is_move_constructible_v<Tdecltype((value()))> is true.

    […]

    template<class F> constexpr auto transform(F&& f) &;
    template<class F> constexpr auto transform(F&& f) const &;
    

    […]

    -18- Constraints: is_copy_constructible_v<Edecltype((error()))> is true.

    […]

    template<class F> constexpr auto transform(F&& f) &&;
    template<class F> constexpr auto transform(F&& f) const &&;
    

    […]

    -22- Constraints: is_move_constructible_v<Edecltype((error()))> is true.

    […]

    template<class F> constexpr auto transform_error(F&& f) &;
    template<class F> constexpr auto transform_error(F&& f) const &;
    

    […]

    -26- Constraints: is_copy_constructible_v<Tdecltype((value()))> is true.

    […]

    template<class F> constexpr auto transform_error(F&& f) &&;
    template<class F> constexpr auto transform_error(F&& f) const &&;
    

    […]

    -30- Constraints: is_move_constructible_v<Tdecltype((value()))> is true.

  2. Modify [expected.void.monadic] as indicated:

    template<class F> constexpr auto and_then(F&& f) &;
    template<class F> constexpr auto and_then(F&& f) const &;
    

    […]

    -2- Constraints: is_copy_constructible_v<Edecltype((error()))> is true.

    […]

    template<class F> constexpr auto and_then(F&& f) &&;
    template<class F> constexpr auto and_then(F&& f) const &&;
    

    […]

    -6- Constraints: is_move_constructible_v<Edecltype((error()))> is true.

    […]

    template<class F> constexpr auto transform(F&& f) &;
    template<class F> constexpr auto transform(F&& f) const &;
    

    […]

    -16- Constraints: is_copy_constructible_v<Edecltype((error()))> is true.

    […]

    template<class F> constexpr auto transform(F&& f) &&;
    template<class F> constexpr auto transform(F&& f) const &&;
    

    […]

    -20- Constraints: is_move_constructible_v<Edecltype((error()))> is true.

    […]