817. bind needs to be moved

Section: 23.14.11.3 [func.bind.bind] Status: C++11 Submitter: Howard Hinnant Opened: 2008-03-17 Last modified: 2016-02-10

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 and th2,

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 to th1's lambda expression in a Move Constructor of lambda expression because th1's lambda expression has a Move Constructor. But bind of th2'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 as CopyConstructible.

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.

  1. bind needs to be "moved".
  2. 23.14.11.3 [func.bind.bind]/p3, p6 and p7 were accidently removed from N2798.
  3. 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 23.14 [function.objects] p2:

template<class Fn, class... Types BoundArgs>
  unspecified bind(Fn&&, Types BoundArgs&&...);
template<class R, class Fn, class... Types BoundArgs>
  unspecified bind(Fn&&, Types BoundArgs&&...);

Change 23.14.3 [func.require]:

4 Every call wrapper (23.14.2 [func.def]) shall be CopyMoveConstructible. A simple call wrapper is a call wrapper that is CopyConstructible and CopyAssignable 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 form

template<class... ArgTypesUnBoundsArgs>
R operator()(ArgTypesUnBoundsArgs&&... unbound_args) cv-qual;

end note]

Change 23.14.11.3 [func.bind.bind]:

Within this clause:

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

-1- Requires: is_constructible<FD, F>::value shall be true. For each Ti in BoundArgs, is_constructible<TiD, Ti>::value shall be true. F and each Ti in BoundArgs shall be CopyConstructible. INVOKE(fd, w1, w2, ..., wN) (23.14.3 [func.require]) shall be a valid expression for some values w1, w2, ..., wN, where N == sizeof...(bound_args).

-2- Returns: A forwarding call wrapper g with a weak result type (23.14.3 [func.require]). The effect of g(u1, u2, ..., uM) shall be INVOKE(fd, v1, v2, ..., vN, result_of<FD cv (V1, V2, ..., VN)>::type), 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.

-3- Throws: Nothing unless the copy constructionor of Ffd or of one of the values tid types in the BoundArgs... pack expansion throws an exception.

Remarks: The unspecified return type shall satisfy the requirements of MoveConstructible. If all of FD and TiD satisfy the requirements of CopyConstructible then the unspecified return type shall satisfy the requirements of CopyConstructible. [Note: This implies that all of FD and TiD shall be MoveConstructibleend note]

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

-4- Requires: is_constructible<FD, F>::value shall be true. For each Ti in BoundArgs, is_constructible<TiD, Ti>::value shall be true. F and each Ti in BoundArgs shall be CopyConstructible. INVOKE(fd, w1, w2, ..., wN) shall be a valid expression for some values w1, w2, ..., wN, where N == sizeof...(bound_args).

-5- Returns: A forwarding call wrapper g with a nested type result_type defined as a synonym for R. The effect of g(u1, u2, ..., uM) shall be INVOKE(fd, v1, v2, ..., vN, R), where 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.

-6- Throws: Nothing unless the copy constructionor of Ffd or of one of the values tid types in the BoundArgs... pack expansion throws an exception.

Remarks: The unspecified return type shall satisfy the requirements of MoveConstructible. If all of FD and TiD satisfy the requirements of CopyConstructible then the unspecified return type shall satisfy the requirements of CopyConstructible. [Note: This implies that all of FD and TiD shall be MoveConstructibleend note]

-7- The values of the bound arguments v1, v2, ..., vN and their corresponding types V1, V2, ..., VN depend on the types TiD derived from of the corresponding argument ti in bound_args of type Ti in BoundArgs in the call to bind and the cv-qualifiers cv of the call wrapper g as follows: