2420. function<void(ArgTypes...)> does not discard the return value of the target object

Section: 22.10.17.3 [func.wrap.func] Status: C++17 Submitter: Agustín Bergé Opened: 2014-07-12 Last modified: 2017-07-30

Priority: 1

View all other issues in [func.wrap.func].

View all issues with C++17 status.

Discussion:

function<void(ArgTypes...)> should discard the return value of the target object. This behavior was in the original proposal, and it was removed (accidentally?) by the resolution of LWG 870.

Previous resolution [SUPERSEDED]:

  1. Edit 22.10.17.3 [func.wrap.func] paragraph 2:

    A callable object f of type F is Callable for argument types ArgTypes and return type R if the expression INVOKE(f, declval<ArgTypes>()..., R), considered as an unevaluated operand (Clause 5), is well formed (22.10.4 [func.require]) and, if R is not void, implicitly convertible to R.

[2014-10-05 Daniel comments]

This side-effect was indeed not intended by 870.

[2015-05, Lenexa]

STL provides improved wording. It replaces the current PR, and intentionally leaves 22.10.17.3 [func.wrap.func] unchanged.

Due to 7 [expr]/6, static_cast<void> is correct even when R is const void.

Proposed resolution:

This wording is relative to N4431.

  1. Edit 22.10.4 [func.require] as depicted:

    -2- Define INVOKE(f, t1, t2, ..., tN, R) as static_cast<void>(INVOKE(f, t1, t2, ..., tN)) if R is cv void, otherwise INVOKE(f, t1, t2, ..., tN) implicitly converted to R.

  2. Change 22.10.17.3.5 [func.wrap.func.inv] as depicted:

    R operator()(ArgTypes... args) const;
    

    -1- EffectsReturns: INVOKE(f, std::forward<ArgTypes>(args)..., R) (20.9.2), where f is the target object (20.9.1) of *this.

    -2- Returns: Nothing if R is void, otherwise the return value of INVOKE(f, std::forward<ArgTypes>(args)..., R).