Title
packaged_task should reject rvalue reference return types
Status
new
Section
[futures.task.general]
Submitter
Casey Carter

Created on 2024-09-28.00:00:00 last changed 3 days ago

Messages

Date: 2025-02-07.16:58:32

Proposed resolution:

This wording is relative to N5001.

  1. Modify [futures.task.general] as indicated:

    […]

    -2- When the packaged_task object is invoked, its stored task is invoked and the result (whether normal or exceptional) stored in the shared state. Any futures that share the shared state will then be able to access the stored result.

    namespace std {
      template<class> class packaged_task; // not defined
    
      template<class R, class... ArgTypes>
      class packaged_task<R(ArgTypes...)> {
        […]
      };
    
      template<class R, class... ArgTypes>
      packaged_task(R (*)(ArgTypes...)) -> packaged_task<R(ArgTypes...)>;
    
      template<class F> packaged_task(F) -> packaged_task<see below>;
    }
    

    -?- If the definition of a specialization packaged_task<R(Args...)> is instantiated for an rvalue reference type `R`, the program is ill-formed.

Date: 2025-02-15.00:00:00

[ 2025-02-07; Jonathan provides improved wording ]

Date: 2025-02-15.00:00:00

[ 2025-02-07; Reflector poll ]

Set priority to 3 after reflector poll.

"Shouldn't it be ill-formed only if instantiated?"

This wording is relative to N4988.

  1. Modify [futures.task.general] as indicated:

    […]

    -2- When the packaged_task object is invoked, its stored task is invoked and the result (whether normal or exceptional) stored in the shared state. Any futures that share the shared state will then be able to access the stored result.

    namespace std {
      template<class> class packaged_task; // not defined
      
      template<class R, class... ArgTypes>
      class packaged_task<R(ArgTypes...)> {
        […]
      };
      
      template<class R, class... ArgTypes>
      packaged_task(R (*)(ArgTypes...)) -> packaged_task<R(ArgTypes...)>;
      
      template<class F> packaged_task(F) -> packaged_task<see below>;
    }
    

    -?- The program is ill-formed if R is an rvalue reference type.

Date: 2024-09-28.00:00:00

`promise`, `future`, and `shared_future` all refuse rvalue reference types as template arguments (e.g., [futures.promise] paragraphs 1 and 2), but packaged_task<meow&&()> violates no requirements. Its member `get_future` returns future<meow&&>, which is ill-formed, but the other member functions appear to be callable. Nonetheless, at least MSVCSTL, libc++, and libstdc++ all fail to compile simple uses of `packaged_task` with a function type that has an rvalue reference return type (see https://www.godbolt.org/z/5E18nn896).

Presumably the design intent — which the implementers all inferred — is that `packaged_task` should be ill-formed when `get_future` is not instantiable. The spec should say so explicitly rather than relying on the fact that one of the basis operations is unusable.

History
Date User Action Args
2025-02-07 16:58:32adminsetmessages: + msg14587
2025-02-07 16:57:42adminsetmessages: + msg14584
2024-10-03 12:20:03adminsetmessages: + msg14414
2024-09-28 00:00:00admincreate