Title
bind's specification doesn't apply the cv-qualification of the call wrapper to the callable object
Status
resolved
Section
[func.bind.bind]
Submitter
Tim Song

Created on 2017-05-04.00:00:00 last changed 52 months ago

Messages

Date: 2020-01-13.07:01:29

Proposed resolution:

This wording is relative to N4659.

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

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

    […]

    -3- Returns: A forwarding call wrapper g ([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 ([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) — […]

Date: 2020-01-13.07:01:29

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

Date: 2017-07-15.22:58:07

[ 2017-07 Toronto Wed Issue Prioritization ]

Priority 3

Date: 2017-05-04.00:00:00

According to [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.

History
Date User Action Args
2020-01-13 07:01:29adminsetmessages: + msg10924
2020-01-13 07:01:29adminsetstatus: new -> resolved
2017-07-15 22:58:07adminsetmessages: + msg9382
2017-05-07 16:39:10adminsetmessages: + msg9171
2017-05-04 00:00:00admincreate