This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.
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(i).
US 72:
bindshould support move-only functors and bound arguments.
JP 38:
add the move requirement for bind's return type.
For example, assume following
th1andth2,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,
vis moved toth1's lambda expression in a Move Constructor of lambda expression becauseth1's lambda expression has a Move Constructor. Butbindofth2'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
MoveConstructibleas 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.
bindneeds to be "moved".- 22.10.15.4 [func.bind.bind]/p3, p6 and p7 were accidently removed from N2798.
- Issue 929(i) argues for a way to pass by && for efficiency but retain the decaying behavior of pass by value for the
threadconstructor. 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 isCopyMoveConstructibleCopyConstructibleandCopyAssignableand 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
FDbe a synonym for the typedecay<F>::type.- Let
fdbe an lvalue of typeFDconstructed fromstd::forward<F>(f).- Let
Tibe a synonym for the ith type in the template parameter packBoundArgs.- Let
TiDbe a synonym for the typedecay<Ti>::type.- Let
tibe the ith argument in the function parameter packbound_args.- Let
tidbe an lvalue of typeTiDconstructed fromstd::forward<Ti>(ti).- Let
Ujbe the jth deduced type of theUnBoundArgs&&...parameter of theoperator()of the forwarding call wrapper.- Let
ujbe the jth argument associated withUj.template<class F, class... BoundArgs> unspecified bind(F&& f, BoundArgs&&... bound_args);-1- Requires:
is_constructible<FD, F>::valueshall betrue. For eachTiinBoundArgs,is_constructible<TiD, Ti>::valueshall betrue.Fand eachTiinBoundArgsshall 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
gwith 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 ofgand the values and types of the bound argumentsv1, v2, ..., vNare 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 ofFDor of any of the typesTiDthrows an exception.-3- Throws: Nothing unless the
copyconstructionorofor of one of the valuesFfdtidtypes in thethrows an exception.BoundArgs...pack expansionRemarks: The unspecified return type shall satisfy the requirements of
MoveConstructible. If all ofFDandTiDsatisfy the requirements ofCopyConstructiblethen the unspecified return type shall satisfy the requirements ofCopyConstructible. [Note: This implies that all ofFDandTiDshall beMoveConstructible— end note]template<class R, class F, class... BoundArgs> unspecified bind(F&& f, BoundArgs&&... bound_args);-4- Requires:
is_constructible<FD, F>::valueshall betrue. For eachTiinBoundArgs,is_constructible<TiD, Ti>::valueshall betrue.Fand eachTiinBoundArgsshall 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
gwith a nested typeresult_typedefined 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, ..., vNare 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 ofFDor of any of the typesTiDthrows an exception.-6- Throws: Nothing unless the
copyconstructionorofor of one of the valuesFfdtidtypes in thethrows an exception.BoundArgs...pack expansionRemarks: The unspecified return type shall satisfy the requirements of
MoveConstructible. If all ofFDandTiDsatisfy the requirements ofCopyConstructiblethen the unspecified return type shall satisfy the requirements ofCopyConstructible. [Note: This implies that all ofFDandTiDshall beMoveConstructible— end note]-7- The values of the bound arguments
v1, v2, ..., vNand their corresponding typesV1, V2, ..., VNdepend on the typesTiDderived fromof the corresponding argumentthe call totiinbound_argsof typeTiinBoundArgsinbindand the cv-qualifiers cv of the call wrappergas follows:
- if
istiTiDof typereference_wrapper<T>the argument istid.get()and its typeViisT&;- if the value of
isstd::is_bind_expression<TiD>::valuetruethe argument istid(std::forward<Uj>(uj)...and its typeu1, u2, ..., uM)Viisresult_of<TiD cv (Uj...;U1&, U2&, ..., UM&)>::type- if the value
jofis not zero the argument isstd::is_placeholder<TiD>::valuestd::forward<Uj>(uj)and its typeViisUj&&;- otherwise the value is
tidand its typeViisTiD cv &.