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

2781. Contradictory requirements for std::function and std::reference_wrapper

Section: 22.10.17.3.2 [func.wrap.func.con] Status: C++17 Submitter: Jonathan Wakely Opened: 2016-10-13 Last modified: 2017-07-30

Priority: 0

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

View all issues with C++17 status.

Discussion:

template<class F> function(F f) says that the effects are "*this targets a copy of f" which seems pretty clear that if F is reference_wrapper<CallableType> then the target is a reference_wrapper<CallableType>.

But the function copy and move constructors say "shall not throw exceptions if f's target is a callable object passed via reference_wrapper or a function pointer." From the requirement above it's impossible for the target to be "a callable object passed via reference_wrapper" because if the function was constructed with such a type then the target is the reference_wrapper not the callable object it wraps.

This matters because it affects the result of function::target_type(), and we have implementation divergence. VC++ and libc++ store the reference_wrapper as the target, but libstdc++ and Boost.Function (both written by Doug Gregor) unwrap it, so the following fails:

#include <functional>
#include <cassert>

int main()
{
 auto f = []{};
 std::function<void()> fn(std::ref(f));
 assert(fn.target<std::reference_wrapper<decltype(f)>>() != nullptr);
}

If std::function is intended to deviate from boost::function this way then the Throws element for the copy and move constructors is misleading, and should be clarified.

[2016-11-12, Issaquah]

Sat AM: Priority 0; move to Ready

Proposed resolution:

This wording is relative to N4606.

  1. Modify 22.10.17.3.2 [func.wrap.func.con] p4 and p6 the same way, as shown:

    function(const function& f);
    

    -3- Postconditions: !*this if !f; otherwise, *this targets a copy of f.target().

    -4- Throws: shall not throw exceptions if f's target is a callable object passed viaspecialization of reference_wrapper or a function pointer. Otherwise, may throw bad_alloc or any exception thrown by the copy constructor of the stored callable object. [Note: Implementations are encouraged to avoid the use of dynamically allocated memory for small callable objects, for example, where f's target is an object holding only a pointer or reference to an object and a member function pointer. — end note]

    function(function&& f);
    

    -5- Effects: If !f, *this has no target; otherwise, move constructs the target of f into the target of *this, leaving f in a valid state with an unspecified value.

    -6- Throws: shall not throw exceptions if f's target is a callable object passed viaspecialization of reference_wrapper or a function pointer. Otherwise, may throw bad_alloc or any exception thrown by the copy or move constructor of the stored callable object. [Note: Implementations are encouraged to avoid the use of dynamically allocated memory for small callable objects, for example, where f's target is an object holding only a pointer or reference to an object and a member function pointer. — end note]

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy