Title
Simplify wording for bind without explicitly specified return type
Status
c++17
Section
[func.bind.bind]
Submitter
Tomasz Kamiński

Created on 2015-10-05.00:00:00 last changed 81 months ago

Messages

Date: 2015-11-04.16:49:21

Proposed resolution:

This wording is relative to N4527.

  1. Change [func.bind.bind] p3 as indicated:

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

    […]

    -3- Returns: A forwarding call wrapper g with a weak result type (20.9.2). The effect of g(u1, u2, ..., uM) shall be INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN), result_of_t<FD cv & (V1, V2, ..., 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 TiD throws an exception.

    […]

Date: 2015-11-04.16:49:21

[ 2015-10, Kona Saturday afternoon ]

STL: I most recently reimplemented std::bind from scratch, and I think this issue is correct and the solution is good.

Move to Tentatively ready.

Date: 2015-10-05.00:00:00

The specification of the bind overload without return type as of [func.bind.bind] p3, uses the following expression INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN), result_of_t<FD cv & (V1, V2, ..., VN)>) to describe effects of invocation of returned function.

According to the definition from [meta.trans.other] result_of_t<FD cv & (V1, V2, ..., VN)> is equivalent to decltype(INVOKE(declval<FD cv &>(), declval<V1>(), declval<V2>(), ..., declval<VN>())). When combined with the definition of INVOKE from [func.require] p2, the expression INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN), result_of_t<FD cv & (V1, V2, ...., VN)>) is equivalent to INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN)) implicitly converted to decltype(INVOKE(declval<FD cv &>(), declval<V1>(), declval<V2>(), ..., declval<VN>())) (itself).

It is also worth to notice that specifying the result type (R) in INVOKE(f, args..., R) does not in any way affect the selected call. As a consequence the use of wording of the form INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN), result_of_t<FD cv & (V1, V2, ..., VN)>) does not and cannot lead to call of different overload than one invoked by INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN)).

In summary the form INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN), result_of_t<FD cv & (V1, V2, ..., VN)>) is a convoluted way of expressing INVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN)), that only confuses reader.

History
Date User Action Args
2017-07-30 20:15:43adminsetstatus: wp -> c++17
2016-03-07 04:11:48adminsetstatus: ready -> wp
2015-12-22 10:31:54adminsetstatus: new -> ready
2015-11-04 16:49:21adminsetmessages: + msg7617
2015-10-12 18:49:53adminsetmessages: + msg7564
2015-10-05 00:00:00admincreate