2487. bind() should be const-overloaded, not cv-overloaded

Section: 22.10.15.4 [func.bind.bind] Status: C++17 Submitter: Stephan T. Lavavej Opened: 2015-03-27 Last modified: 2017-07-30

Priority: 2

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

View all issues with C++17 status.

Discussion:

The Standard currently requires bind() to return something with a cv-overloaded function call operator. const is great, but volatile is not. First, the Library almost always ignores volatile's existence (with <type_traits> and <atomic> being rare exceptions). Second, implementations typically store bound arguments in a tuple, but get() isn't overloaded for volatile tuple. Third, when a bound argument is a reference_wrapper, we have to call tid.get(), but that won't compile for a volatile reference_wrapper. Finally, const and volatile don't always have to be handled symmetrically — for example, lambda function call operators are const by default, but they can't ever be volatile.

Implementers shouldn't be required to provide cv-overloading here. (They can provide it as a conforming extension if they want.)

[2015-05, Lenexa]

JW: why would a reference_wrapper be volatile?
STL: if a bound argument is a reference_wrapper then in a volatile-qualified operator() that member will be volatile so you can't call get() on it
STL: worded like this it's a conforming extension to kep overloading on volatile
HH: libc++ doesn't overload on volatile
JW: libstdc++ does overload for volatile
MC: move to Ready and bring motion on Friday
10 in favor, none opposed

Proposed resolution:

This wording is relative to N4296.

  1. Change 22.10.15.4 [func.bind.bind] as depicted:

    template<class F, class... BoundArgs>
      unspecified bind(F&& f, BoundArgs&&... bound_args);
    

    -2- Requires: is_constructible<FD, F>::value shall be true. For each Ti in BoundArgs, is_constructible<TiD, Ti>::value shall be true. INVOKE(fd, w1, w2, ..., wN) (20.9.2) shall be a valid expression for some values w1, w2, ..., wN, where N == sizeof...(bound_args). The cv-qualifiers cv of the call wrapper g, as specified below, shall be neither volatile nor const volatile.

    […]

    template<class R, class F, class... BoundArgs>
      unspecified bind(F&& f, BoundArgs&&... bound_args);
    

    -6- Requires: is_constructible<FD, F>::value shall be true. For each Ti in BoundArgs, is_constructible<TiD, Ti>::value shall be true. INVOKE(fd, w1, w2, ..., wN) shall be a valid expression for some values w1, w2, ..., wN, where N == sizeof...(bound_args). The cv-qualifiers cv of the call wrapper g, as specified below, shall be neither volatile nor const volatile.

    […]