This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.

4175. get_env() specified in terms of as_const() but this doesn't work with rvalue senders

Section: 33.5.2 [exec.get.allocator], 33.5.3 [exec.get.stop.token], 33.5.4 [exec.get.env], 33.5.5 [exec.get.domain], 33.5.6 [exec.get.scheduler], 33.5.7 [exec.get.delegation.scheduler], 33.5.8 [exec.get.fwd.progress], 33.5.9 [exec.get.compl.sched] Status: New Submitter: Lewis Baker Opened: 2024-11-10 Last modified: 2024-11-24

Priority: Not Prioritized

View all issues with New status.

Discussion:

The current specification of std::execution::get_env() defines get_env(o) as as_const(o).get_env(). However, the as_const() function has a deleted rvalue-taking overload, meaning that you cannot pass temporaries to it.

This means that several uses of get_env() which pass expressions which are either potentially rvalues (e.g. in definition of connect(sndr, rcvr) it uses the expression get_env(rcvr), but rcvr could be, and usually is, a prvalue) or always rvalues (e.g. scheduler concept has the expression get_env(schedule(std::forward<Sch>(sch)))).

The intent here was that get_env() is a function that takes as an argument a const T& and thus allows prvalues to bind to it. We basically just want to require that get_env() finds a const-qualified member-function. The use of as_const() does not seem to mirror the semantics of a function with a const T& parameter, so I suggest we change it to something else that expresses the intent.

Proposed resolution:

This wording is relative to N4993.

  1. Add to the end of 33.1 [exec.general] as indicated:

    -?- For a subexpression expr, let AS-CONST(expr) be expression-equivalent to

    [](const auto& x) noexcept -> const auto& { return x; }(expr)
    
  2. Modify 33.5.2 [exec.get.allocator] as indicated:

    -1- get_allocator asks a queryable object for its associated allocator.

    -2- The name get_allocator denotes a query object. For a subexpression env, get_allocator(env) is expression-equivalent to MANDATE-NOTHROW(as_constAS-CONST(env).query(get_allocator)).

  3. Modify 33.5.3 [exec.get.stop.token] as indicated:

    -2- The name get_stop_token denotes a query object. For a subexpression env, get_stop_token(env) is expression-equivalent to:

    1. (2.1) — MANDATE-NOTHROW(as_constAS-CONST(env).query(get_stop_token)) if that expression is well-formed.

  4. Modify 33.5.4 [exec.get.env] as indicated:

    -1- execution::get_env is a customization point object. For a subexpression o, execution::get_env(o) is expression-equivalent to:

    1. (1.1) — MANDATE-NOTHROW(as_constAS-CONST(o).get_env()) if that expression is well-formed.

  5. Modify 33.5.5 [exec.get.domain] as indicated:

    -2- The name get_domain denotes a query object. For a subexpression env, get_domain(env) is expression-equivalent to MANDATE-NOTHROW(as_constAS-CONST(env).query(get_domain)).

  6. Modify 33.5.6 [exec.get.scheduler] as indicated:

    -2- The name get_scheduler denotes a query object. For a subexpression env, get_scheduler(env) is expression-equivalent to MANDATE-NOTHROW(as_constAS-CONST(env).query(get_scheduler)).

  7. Modify 33.5.7 [exec.get.delegation.scheduler] as indicated:

    -2- The name get_delegation_scheduler denotes a query object. For a subexpression env, get_delegation_scheduler(env) is expression-equivalent to MANDATE-NOTHROW(as_constAS-CONST(env).query(get_delegation_scheduler)).

  8. Modify 33.5.8 [exec.get.fwd.progress] as indicated:

    -2- The name get_forward_progress_guarantee denotes a query object. For a subexpression sch, let Sch be decltype((sch)). If Sch does not satisfy scheduler, get_forward_progress_guarantee is ill-formed. Otherwise, get_forward_progress_guarantee(sch) is expression-equivalent to:

    1. (2.1) — MANDATE-NOTHROW(as_constAS-CONST(sch).query(get_forward_progress_guarantee)) if that expression is well-formed.

  9. Modify 33.5.9 [exec.get.compl.sched] as indicated:

    -2- The name get_completion_scheduler denotes a query object template. For a subexpression q, the expression get_completion_scheduler<completion-tag>(q) is ill-formed if completion-tag is not one of set_value_t, set_error_t, or set_stopped_t. Otherwise, get_completion_scheduler<completion-tag>(q) is expression-equivalent to

    MANDATE-NOTHROW(as_constAS-CONST(q).query(get_completion_scheduler<completion-tag>))