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

### 2957. `bind`'s specification doesn't apply the cv-qualification of the call wrapper to the callable object

Section: 20.14.15.4 [func.bind.bind] Status: Resolved Submitter: Tim Song Opened: 2017-05-04 Last modified: 2020-09-06

Priority: 3

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

View all issues with Resolved status.

Discussion:

According to 20.14.15.4 [func.bind.bind]/1.2,

> `fd` is an lvalue of type `FD` constructed from `std::forward<F>(f)`,

and then uses `fd` throughout the specification, seemingly without regard to the cv-qualification of the call wrapper `g`. But this definition means that `fd` is always cv-unqualified, rather than having its cv-qualification change with that of `g` as intended.

LWG 2545 accidentally exacerbated the problem by removing any hint that `fd`'s cv-qualifier followed that of the call wrapper.

A similar issue affects the type of `tdi` for nested binds.

[2017-07 Toronto Wed Issue Prioritization]

Priority 3

[2020-01 Resolved by the adoption of P1065 in Cologne.]

Proposed resolution:

This wording is relative to N4659.

1. Edit 20.14.15.4 [func.bind.bind] as indicated:

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

   > > […]

   > > -3- Returns: A forwarding call wrapper `g` (20.14.4 [func.require]). The effect of `g(u1, u2, ..., uM)` shall be

   > > >     INVOKE(static_cast<FD cv &>(fd), std::forward<V1>(v1),
   > > >       std::forward<V2>(v2), ..., std::forward<VN>(vN))

   > > where cv represents the cv-qualifiers of `g` and the values and types of the bound arguments `v1, v2, . . . , vN` are determined as specified below. The copy constructor and move constructor of the forwarding call wrapper shall throw an exception if and only if the corresponding constructor of `FD` or of any of the types `TDi` throws an exception.

   > > […]

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

   > > […]

   > > -7- Returns: A forwarding call wrapper `g` (20.14.4 [func.require]). The effect of `g(u1, u2, ..., uM)` shall be

   > > >     INVOKE<R>(static_cast<FD cv &>(fd), std::forward<V1>(v1),
   > > >       std::forward<V2>(v2), ..., std::forward<VN>(vN))

   > > where cv represents the cv-qualifiers of `g` and the values and types of the bound arguments `v1, v2, . . . , vN` are determined as specified below. The copy constructor and move constructor of the forwarding call wrapper shall throw an exception if and only if the corresponding constructor of `FD` or of any of the types `TDi` throws an exception.

   > > […]

   > > -10- The values of the bound arguments `v1, v2, ... , vN` and their corresponding types `V1, V2, ... , VN` depend on the types `TDi` derived from the call to `bind` and the cv-qualifiers cv of the call wrapper `g` as follows:

   > > 1. (10.1) — […]

   > > 2. (10.2) — if the value of `is_bind_expression_v<TDi>` is `true`, the argument is `static_cast<TDi cv &>(tdi)(std::forward<Uj>(uj)...)` and its type `Vi` is `invoke_result_t<TDi cv &, Uj...>&&`;

   > > 3. (10.3) — […]