bind
needs to be movedSection: 22.10.15.4 [func.bind.bind] Status: C++11 Submitter: Howard Hinnant Opened: 2008-03-17 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [func.bind.bind].
View all issues with C++11 status.
Discussion:
Addresses US 72, JP 38 and DE 21
The functor returned by bind()
should have a move constructor that
requires only move construction of its contained functor and bound arguments.
That way move-only functors can be passed to objects such as thread
.
This issue is related to issue 816.
US 72:
bind
should support move-only functors and bound arguments.
JP 38:
add the move requirement for bind's return type.
For example, assume following
th1
andth2
,void f(vector<int> v) { } vector<int> v{ ... }; thread th1([v]{ f(v); }); thread th2(bind(f, v));When function object are set to thread,
v
is moved toth1
's lambda expression in a Move Constructor of lambda expression becauseth1
's lambda expression has a Move Constructor. Butbind
ofth2
's return type doesn't have the requirement of Move, so it may not moved but copied.Add the requirement of move to get rid of this useless copy.
And also, add the
MoveConstructible
as well asCopyConstructible
.
DE 21
The specification for bind claims twice that "the values and types for the bound arguments v1, v2, ..., vN are determined as specified below". No such specification appears to exist.
[ San Francisco: ]
Howard to provide wording.
[ Post Summit Alisdair and Howard provided wording. ]
Several issues are being combined in this resolution. They are all touching the same words so this is an attempt to keep one issue from stepping on another, and a place to see the complete solution in one place.
bind
needs to be "moved".- 22.10.15.4 [func.bind.bind]/p3, p6 and p7 were accidently removed from N2798.
- Issue 929 argues for a way to pass by && for efficiency but retain the decaying behavior of pass by value for the
thread
constructor. That same solution is applicable here.
[ Batavia (2009-05): ]
We were going to recommend moving this issue to Tentatively Ready until we noticed potential overlap with issue 816 (q.v.).
Move to Open, and recommend both issues be considered together (and possibly merged).
[ 2009-07 Frankfurt: ]
The proposed resolution uses concepts. Leave Open.
[ 2009-10 Santa Cruz: ]
Leave as Open. Howard to provide deconceptified wording.
[ 2009-11-07 Howard updates wording. ]
[ 2009-11-15 Further updates by Peter, Chris and Daniel. ]
[ Moved to Tentatively Ready after 6 positive votes on c++std-lib. ]
Proposed resolution:
Change 22.10 [function.objects] p2:
template<class Fn, class...TypesBoundArgs> unspecified bind(Fn&&,TypesBoundArgs&&...); template<class R, class Fn, class...TypesBoundArgs> unspecified bind(Fn&&,TypesBoundArgs&&...);
Change 22.10.4 [func.require]:
4 Every call wrapper (22.10.3 [func.def]) shall be
. A simple call wrapper is a call wrapper that is
CopyMoveConstructibleCopyConstructible
andCopyAssignable
and whose copy constructor, move constructor and assignment operator do not throw exceptions. A forwarding call wrapper is a call wrapper that can be called with an argument list. [Note: in a typical implementation forwarding call wrappers have an overloaded function call operator of the formtemplate<class...ArgTypesUnBoundsArgs> R operator()(ArgTypesUnBoundsArgs&&... unbound_args) cv-qual;— end note]
Change 22.10.15.4 [func.bind.bind]:
Within this clause:
- Let
FD
be a synonym for the typedecay<F>::type
.- Let
fd
be an lvalue of typeFD
constructed fromstd::forward<F>(f)
.- Let
Ti
be a synonym for the ith type in the template parameter packBoundArgs
.- Let
TiD
be a synonym for the typedecay<Ti>::type
.- Let
ti
be the ith argument in the function parameter packbound_args
.- Let
tid
be an lvalue of typeTiD
constructed fromstd::forward<Ti>(ti)
.- Let
Uj
be the jth deduced type of theUnBoundArgs&&...
parameter of theoperator()
of the forwarding call wrapper.- Let
uj
be the jth argument associated withUj
.template<class F, class... BoundArgs> unspecified bind(F&& f, BoundArgs&&... bound_args);-1- Requires:
is_constructible<FD, F>::value
shall betrue
. For eachTi
inBoundArgs
,is_constructible<TiD, Ti>::value
shall betrue
.F
and eachTi
inBoundArgs
shall be CopyConstructible.INVOKE(fd, w1, w2, ..., wN)
(22.10.4 [func.require]) shall be a valid expression for some values w1, w2, ..., wN, whereN == sizeof...(bound_args)
.-2- Returns: A forwarding call wrapper
g
with a weak result type (22.10.4 [func.require]). The effect ofg(u1, u2, ..., uM)
shall beINVOKE(fd, v1, v2, ..., vN, result_of<FD cv (V1, V2, ..., VN)>::type)
, where cv represents the cv-qualifiers ofg
and the values and types of the bound argumentsv1, 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.-3- Throws: Nothing unless the
copyconstructionorofor of one of the values
Ffdtid
types in thethrows an exception.BoundArgs...
pack expansionRemarks: The unspecified return type shall satisfy the requirements of
MoveConstructible
. If all ofFD
andTiD
satisfy the requirements ofCopyConstructible
then the unspecified return type shall satisfy the requirements ofCopyConstructible
. [Note: This implies that all ofFD
andTiD
shall beMoveConstructible
— end note]template<class R, class F, class... BoundArgs> unspecified bind(F&& f, BoundArgs&&... bound_args);-4- Requires:
is_constructible<FD, F>::value
shall betrue
. For eachTi
inBoundArgs
,is_constructible<TiD, Ti>::value
shall betrue
.F
and eachTi
inBoundArgs
shall be CopyConstructible.INVOKE(fd, w1, w2, ..., wN)
shall be a valid expression for some values w1, w2, ..., wN, whereN == sizeof...(bound_args)
.-5- Returns: A forwarding call wrapper
g
with a nested typeresult_type
defined as a synonym forR
. The effect ofg(u1, u2, ..., uM)
shall beINVOKE(fd, v1, v2, ..., vN, R)
, where the values and types of the bound argumentsv1, 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.-6- Throws: Nothing unless the
copyconstructionorofor of one of the values
Ffdtid
types in thethrows an exception.BoundArgs...
pack expansionRemarks: The unspecified return type shall satisfy the requirements of
MoveConstructible
. If all ofFD
andTiD
satisfy the requirements ofCopyConstructible
then the unspecified return type shall satisfy the requirements ofCopyConstructible
. [Note: This implies that all ofFD
andTiD
shall beMoveConstructible
— end note]-7- The values of the bound arguments
v1, v2, ..., vN
and their corresponding typesV1, V2, ..., VN
depend on the typesTiD
derived fromof the corresponding argumentthe call toti
inbound_args
of typeTi
inBoundArgs
inbind
and the cv-qualifiers cv of the call wrapperg
as follows:
- if
is
tiTiDof typereference_wrapper<T>
the argument istid.get()
and its typeVi
isT&
;- if the value of
is
std::is_bind_expression<TiD>::valuetrue
the argument istid(std::forward<Uj>(uj)...
and its typeu1, u2, ..., uM)Vi
isresult_of<TiD cv (Uj...
;U1&, U2&, ..., UM&)>::type- if the value
j
ofis not zero the argument is
std::is_placeholder<TiD>::valuestd::forward<Uj>(uj)
and its typeVi
isUj&&
;- otherwise the value is
tid
and its typeVi
isTiD cv &
.