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.
bind
without explicitly specified return typeSection: 22.10.15.4 [func.bind.bind] Status: C++17 Submitter: Tomasz Kamiński Opened: 2015-10-05 Last modified: 2017-07-30
Priority: 3
View all other issues in [func.bind.bind].
View all issues with C++17 status.
Discussion:
The specification of the bind
overload without return type as of 22.10.15.4 [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.
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 22.10.4 [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.
[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.
Proposed resolution:
This wording is relative to N4527.
Change 22.10.15.4 [func.bind.bind] p3 as indicated:
template<class F, class... BoundArgs> unspecified bind(F&& f, BoundArgs&&... bound_args);[…]
-3- Returns: A forwarding call wrapperg
with a weak result type (20.9.2). The effect ofg(u1, u2, ..., uM)
shall beINVOKE(fd, std::forward<V1>(v1), std::forward<V2>(v2), ..., std::forward<VN>(vN)
, where, result_of_t<FD cv & (V1, V2, ..., VN)>)the values and types of the bound argumentscv
represents the cv-qualifiers ofg
andv1, 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 ofFD
or of any of the typesTiD
throws an exception. […]